深度搜素 搜尋巢狀

2021-07-05 23:29:11 字數 2794 閱讀 6847

搜尋問題,擴充套件節點的時候會iterate乙個link集合,一般就是乙個for 迴圈,但有的時候,這個集合並不能直接得到,而是另乙個搜尋問題,比如n個數分k組問題的一種解法是:問題分成k個步驟,每個步驟確定乙個組,具體乙個組可分的方案的candidate集合就不是直接可以用for來iterate的,而是另乙個搜尋問題——子集問題。這就引出乙個重點,iterate不光可以額用for,也可以用搜尋,搜尋本來就是在列舉,只不過列舉出乙個解不是print輸出,而是用來作為外層搜尋的乙個擴充套件節點,另外一點,搜尋的結果體現在哪?side effect,搜尋一般是通過side effect體現狀態、結果的。

更新:巢狀搜尋的思路只是乙個看問題的角度,把維度拆開來乙個乙個看。也可以有另一種更general的角度:二元(多元)搜尋。每一次遞迴就是一次狀態轉移,一般的,這個狀態是乙個變數,其他的變數都是伴隨狀態;多元搜尋的意思是狀態是乙個組合(x, y),類似二維平面上的搜尋,看下面終極版搜尋。

def group(a, k):

groups, n, used = [ for _ in xrange(k)], len(a), set()

def grouping(t, start):

if t == k:

if len(used) == n: print groups

return

if start == n: return

if start in used: grouping(t, start + 1)

else:

used.add(start)

def select(i, startindex):

grouping(t + 1, start + 1)

for j in xrange(startindex, n):

if j in used: continue

used.add(j)

select(i + 1, j + 1)

used.remove(j)

groups[t].pop()

select(start + 1, start + 1)

groups[t].pop()

used.remove(start)

grouping(0, 0)

第二個版本

def group(a, k):

groups, n, used = [ for _ in xrange(k)], len(a), set()

def grouping(t, start):

if t == k:

if len(used) == n: print groups

return

if start == n: return

if start in used: grouping(t, start + 1)

else:

def select(i, startindex):

grouping(t + 1, start + 1)

for j in xrange(startindex, n):

if j in used: continue

used.add(j)

select(i + 1, j + 1)

used.remove(j)

groups[t].pop()

select(start, start)

grouping(0, 0)

遞迴問題法:

def group(a, k):

if k == 1:return [[a[:]]]

if k == len(a): return [map(lambda x: [x], a)]

last = a.pop()

groupings = group(a, k - 1)

for grouping in group(a, k):

for g in grouping:

g.pop()

return groupings

終極版本:

def group(a, k):

groups, used = [ for _ in xrange(k)], set()

def grouping(g, start):

if g == k:

if len(used) == len(a): print groups

else:

if len(groups[g]) > 0: grouping(g + 1, g + 1)

for i in xrange(start, len(a)):

if i in used: continue

used.add(i)

grouping(g, i + 1)

groups[g].pop()

used.remove(i)

grouping(0, 0)

還有乙個例子:leetcode 282 expression add operators,給一串數字加操作符湊乙個給定的值。問題的劃分:每一步取若干數字作為乙個數,參與計算,下一步取剩下的,取完為止。每一步按取幾個數字作為數又分多種情況,同時確定了乙個數之後按進行什麼運算分又有4種情況。這裡擴充套件節點是乙個雙重迴圈,先列舉取幾個數字作為運算元,再列舉4種運算。

vectoraddoperators(string num, int target) 

else

else

}} };

dfs(0, 0, 0, "");

return ans;

}

深度優化搜素(dfs

如果我們想輸出乙個數的全排列,eg 1,2,3 的全排列 那麼就有123,132,213,231,312,321,這六種。那如何用 實現呢?for int a 1 a 3 a 暴力列舉是一種,但是如果數字編的更多呢?如1,2,3,4,5,6,7,8,9呢?如果我們還是乙個乙個列舉出來,別說計算機你也...

4 17部落格(廣度優先搜尋和深度優先搜素)

這週講了搜尋演算法。相比於單純的列舉演算法有了一定的方向性和目標性。演算法是在解的空間裡,從乙個狀態轉移 按照要求拓展 到其他狀態,這樣進行下去,將解的空間中的狀態遍歷,找到答案 目標的狀態 搜尋演算法分為廣度優先搜尋 bfs 和深度優先搜尋 dfs 廣度優先搜尋 基本思想 從初始狀態 s 開始,利...

深度優先搜素及題目

1.搜尋是指已知初始狀態和目標狀態,對問題的中間狀態進行列舉的遍歷的一種演算法,通俗的講,搜尋就是比較複雜的列舉。2.深度優先搜尋是按照深度的方式進行搜尋,就是把所有可行的方案都列舉出來,不斷的去嘗試,直到找到問題的解。設想你在乙個迷宮裡面,當我們在起點時,總要通過各種岔路口才能找到迷宮的終點,那麼...