必看,必刷,dfs 經典:
需要統計所有的方案數,那麼完全揹包在這貌似就不能使用了。就暴力搜所有方案就行了。
暴搜順序是很重要的,在這順序遍歷陣列中的每乙個數,並列舉它可能取的所有個數,就能不重不漏的搜完所有可能方案。
**細節:
dfs
暴搜,一直都被認為是簡單,確實,但是還是得多寫點題,才能考慮到搜尋順序和**邊界、細節情況!
看看官方題解蠻不錯的,**很清楚!
時間複雜度:不會分析…
空間複雜度:不會分析…,這個貌似是 o(t
arge
t)
o(target)
o(targ
et)?就是遞迴深度吧
**:
class
solution
void
dfs(vector<
int>
& c,
int u,
int target)
// 如果列舉完最後乙個數還沒能湊出target,則直接 return
if(u == c.
size()
)return
;// u表示列舉到當前的數
// c[u] * i <= target 選i個,最小單位為1,相乘則表示不能超過target這個值
for(
int i =
0; c[u]
* i <= target;
++i)
// 恢復現場
for(
int i =
0; c[u]
* i <= target;
++i)}}
;
2023年08月24日 個人理解:
這個 dfs 走了個頓挫,就很巧妙。因為一開始c[u]
的選取個數i
是從 0 開始的。所以在進入下一層時,要保證path
中沒有c[u]
存在,所以先讓它進入下一層,然後再給path
中新增乙個c[u]
進去。
這樣就能保證每次進入下一層時,path
中的c[u]
個數和i
的值保持一致。即和定義相同。
並且如果c[u]
乙個都不能選的話,必然在i=1
時跳出for
迴圈,這個尾部加如的 1 個c[u]
就會立馬被恢復現場清掉,並不會產生錯誤的影響,很是巧妙。
class
solution
// 選當前數。i從0 開始,指的是不選當前數的情況
for(
int i =
0; c[u]
* i <= target; i ++
)/* 當i=1時,path 中才會有乙個c[u]存在,並dfs到下一層,而當 i=0時,path中並沒有存在的該元素,就直接dfs到下一層。
由於i=0是必然要執行一次的,因為c[u]*0<=target 必然成立。
但是,如果緊接著 i=1不成立的話,for 迴圈跳出,這個剛加進去的c[u]就會被立馬pop_back掉。並不影響答案
所以這個寫法就保證了,在dfs過程中i與path中c[u]的個數的嚴格對應。
即,一開始,for迴圈進入,是 0 個,dfs進入下一層也是0個,然後回到本層時,才在尾部立馬加 1 個,緊接著 i=1 就進入下一層dfs
此時,path中就有了剛剛那個剛加入的1個c[u]。
所以用這種方式,將 i個c[u]與列舉的層數嚴格對應起來。保證在進入下一層時,當前的c[u]是i個。
即i=0時,進入下一層時,c[u]是0個
i=1時,進入下一層時,c[u]是1個
...仍要多多理解
*/for(
int i =
0; c[u]
* i <= target; i ++
) path.
pop_back()
;}vectorint>>
combinationsum
(vector<
int>
& c,
int target)
};
LeetCode 39 組合總和 DFS
給定乙個無重複元素的陣列 candidates 和乙個目標數 target 找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的數字可以無限制重複被選取。說明 所有數字 包括 target 都是正整數。解集不能包含重複的組合。示例 1 輸入 candid...
力扣 39 組合總和 dfs
不同組合,並以列表形式返回。你可以按任意順序返回這些組合。candidates中的同乙個數字可以無限制重複被選取。如果至少乙個數字的被選數量不同,則兩種組合是不同的。對於給定的輸入,保證和為target的不同組合數少於150個。示例 1 輸入 candidates 2,3,6,7 target 7 ...
39 組合總和
給定乙個無重複元素的陣列 candidates 和乙個目標數 target 找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的數字可以無限制重複被選取。說明 示例 1 輸入 candidates 2,3,6,7 target 7,所求解集為 7 2,2...