回溯法求解陣列全排列和全組合問題 c

2021-10-23 18:38:24 字數 2057 閱讀 8994

回溯法是學習演算法的乙個坎,它將許多**基礎不夠紮實的同學擋在通往更高水平的門外。究其原因,是因為回溯法本身與遞迴有著千絲萬縷的關係,同時也要求學習者具備較強的抽象問題的能力。所以在學習回溯法之前,學習者必須熟練解決一些常見的遞迴問題,如二叉樹的遍歷、lca問題等,這些問題leetcode均有題目,讀者不妨先去練練手再回來。如果能熟練寫出常見遞迴問題的**,回溯法也就如庖丁解牛了。下面介紹兩個回溯法練習的入門題,陣列元素的全排列和全組合求解。

leetcode第46題考察了這個問題。問題很簡單,高中生也懂,如下:

給定乙個 沒有重複 數字的序列,返回其所有可能的全排列。

示例:輸入: [1,2,3]

輸出:[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

]

如果手算這個問題的答案,我們是如何計算呢?

(1)選取排列的第乙個數字,可選1、2、3,按序從陣列中拿出1,

(2)選取排列的第二個數字,由於1已經被選了,可選2、3,先選2,

(3)選取排列的第三個數字,由於1、2被選,只能選3,得到第乙個排列[1,2,3]。

注意在第二步的時候,我們可選2、3,但是我們已經選了2;所以在第三步結束時我們退回第二步,再選3,然後進入第三步,這時可選2,這樣就得到了[1、3、2]。最終退回第一步重複即可得到所有的排列。

在上述的敘述中,有乙個退回的步驟,這就是我們所說的回溯。它是用遞迴實現的,相當於使用了乙個棧儲存了"案發現場",等退回上一次遞迴時,程式繼續執行。有興趣的讀者可以畫一畫上面所說的過程,可以發現這個選擇過程其實就是一棵樹。

下面看看**,我們用visited來標記這個數是否訪問過,curnums是已經選取的數字集合,當它的size和nums的size一致時就結束遞迴。

class

solution

void

dfs(vectorint>>

& res,

const vector<

int>

&nums,vector<

int>

& visited,vector<

int>

& curnums)

for(

int i =

0; i < nums.

size()

;++i)}}

};

高階:leetcode47題。

這個問題題意也不難,求出乙個集合的所有子集,是高中的組合問題。

給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集(冪集)。

說明:解集不能包含重複的子集。

示例:輸入: nums = [1,2,3]

輸出:[

[3],

[1],

[2],

[1,2,3],

[1,3],

[2,3],

[1,2],

]

這個問題比求解排列簡單一些,如果手算的話步驟如下:

(1)從nums中得到1,[1]是子集,加入結果

(2)從nums中得到2,[1,2]是子集,加入結果

(3)從nums中得到3,[1,2,3]是子集,加入結果

從第3步退回第2步,得到[1,3]子集加入結果、退回第1步從2開始搜尋即可。注意我們每次搜尋均從nums當前數字的下乙個數字開始搜尋,這樣確保結果不重複。

class

solution

void

dfs(vectorint>>

& res,

const vector<

int>

& nums,vector<

int>

& curnums,

int start)}}

;

高階:leetcode90題。

回溯法屬於難者不會會者不難的方法,打好遞迴基礎,做到心中可以模擬遞迴過程的話可以很快入門。

全排列和全組合

所謂全排列,就是列印出字串中所有字元的所有排列。例如輸入字串abc,則列印出 a b c 所能排列出來的所有字串abc acb bac bca cab和cba。一般最先想到的方法是暴力迴圈法,即對於每一位,遍歷集合中可能的元素,如果在這一位之前出現過了該元素,跳過該元素。例如對於abc,第一位可以是...

全排列和全組合實現

所謂全排列,就是列印出字串中所有字元的所有排列。例如輸入字串abc,則列印出 a b c 所能排列出來的所有字串abc acb bac bca cab和cba。一般最先想到的方法是暴力迴圈法,即對於每一位,遍歷集合中可能的元素,如果在這一位之前出現過了該元素,跳過該元素。例如對於abc,第一位可以是...

全排列和全組合實現

記得 老趙之前在微博上吐槽說,有的人真是毫無長進,六年前某同事不會寫程式輸出全排列,昨天發郵件還是問我該怎麼寫,這時間浪費到我都看不下去了。那時候就很好奇全排列到底是什麼東西,到底有多難?今天覆習的時候終於碰到這題了,結果果然自己太渣,看了好久都沒明白,實現又是磕磕碰碰的。所以,就把它整理成筆記加深...