尋找最大排列問題

2021-08-16 05:39:35 字數 2139 閱讀 3800

有八個人去看電影。但是有一部分人只喜歡特殊的座位,大部分人不喜歡自己的座位。我們這要去抽象問題,ab都喜歡c的位置,而c喜歡a的位置。

現在我們開始思考這個問題。ab都喜歡c的位置,那麼我們要從ab中挑選出乙個

好的,我們回顧這個過程,我們會發現問題所在。因為最初b的位置沒有人喜歡,所以一開始去除b是最好的做法。

好的,我們沿著這個思路繼續思考,我們先將bg刪除。接著我們發現g刪除後,g所指向的h就沒有被指向了,接著我們很自然地去刪除h。刪除h後,我們發現h指向的e又沒人指向了,所以這個時候我們就要刪除e。刪除e後,我們發現e指向的d又沒人指向了,所以這個時候我們就要刪除d。最後,我們得到的結果就是a, c, f

接著我們要做的就是將上述過程抽象成**

'''

a:最後剩餘的座位

b:所有人喜歡的座位集合

c:沒有人喜歡的座位

'''def

*****_max_perm

(m, a=none):

if a is

none: # the elt. set not supplied?

a = set(range(len(m))) # a =

if len(a) == 1:

return a # base case -- single-elt. a

b = set(m[i] for i in a) # the "pointed to" elements

c = a - b # "not pointed to" elements

if c: # any useless elements?

a.remove(c.pop()) # remove one of them

return *****_max_perm(m, a) # solve remaining problem

return a # all useful -- return all

我們還有乙個更加高效的做法,我們通過對於所有人喜歡的座位集合進行計數,例如a:1b:0c:2,這種做法減少了上面方案中間過程中建立b的開銷。

from collections import counter

defmax_perm

(m):

n = len(m) # how many elements?

a = set(range(n)) # a =

count = counter(m)

q = [i for i in a if count[i] == 0] # useless elements

while q: # while useless elts. left...

i = q.pop() # get one

a.remove(i) # remove it

j = m[i] # who's it pointing to?

count[j] -= 1

# not anymore...

if count[j] == 0: # is j useless now?

return a # return useful elts.

但是這種做法是如此的醜陋,遠沒有第一種做法美妙。

尋找下乙個最大排列

對於給定的排列a1 a2 a3.an依據字典順序來生成下乙個最大的排列。首先找到整數a j 和a j 1 使得a j a j 2 a n 即在這個排列中的最後一對相鄰的整數,使得這個對的第乙個整數小於第二個整數。然後,把 a j 1 a j 2 a n 中,在按照遞增排序j 1到n的數。這樣就得到了...

leetcode 尋找排列組合

題目描述 現在給定乙個只由字元 d 和 i 組成的 秘密簽名。d 表示兩個數字間的遞減關係,i 表示兩個數字間的遞增關係。並且 秘密簽名 是由乙個特定的整數陣列生成的,該陣列唯一地包含 1 到 n 中所有不同的數字 秘密簽名的長度加 1 等於 n 例如,秘密簽名 di 可以由陣列 2,1,3 或 3...

尋找最大子樹

問題描述 給乙個二叉樹,每個節點都是正或負整數,如何找到乙個子樹,它所有節點的和最大?思路 採用自底向上的計算。先計算左右子樹總和值,用左右子樹的總和加上當前節點值,如果當前總和大於最大值,則更新最大值,同時將最大子樹根節點更新為當前根。簡單說,就是後序遍歷。include include usin...