搜尋問題,擴充套件節點的時候會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.深度優先搜尋是按照深度的方式進行搜尋,就是把所有可行的方案都列舉出來,不斷的去嘗試,直到找到問題的解。設想你在乙個迷宮裡面,當我們在起點時,總要通過各種岔路口才能找到迷宮的終點,那麼...