dfs 回溯習題整理(1)

2021-10-05 17:11:49 字數 4218 閱讀 9194

搜尋順序:

按照給出的數字依次進行搜尋,對於每乙個數字列舉它選用每乙個字母的方案。

回溯:當下乙個字串已經列舉完成時,需要更新當前字串,此時需要進行回溯。然後進行列舉,到當前字串的下乙個元素。第一次寫時,迴圈的意義沒有考慮清楚,這個做法的迴圈是列舉當前字串的每個字元,而不是下乙個字串的每個字元。

class

solution

; vector<

string

> ans;

string path, s;

vector<

string

>

lettercombinations

(string _digits)

void

dfs(

int u,

int y)

string

& cur = letter[s[u]

-'2'];

//當前數字對應字串的每乙個字母都要遍歷一遍

for(

int i =

0; i < cur.

size()

; i ++)}

};

搜尋順序:

對矩陣中的每乙個元素依次進行搜尋,對每乙個元素列舉可能能走的四個方向。

回溯:考慮清楚每個迴圈的意義。考慮清楚何時回溯。對於本題來說,當我已經嘗試走過四個方向後,都沒有匹配上,進行回溯。

class

solution

, dy[4]

=;bool

dfs(

int x,

int y,

int u)

b[x]

[y]= w[u]

;return

false;}

bool

exist

(vectorchar

>

>

& board,

string word)

}return

false;}

};

搜尋順序:

對全排列中的位置依次進行搜尋,對每乙個位置列舉可能能填上的數。

回溯:當第u+1個位置的所有方案填完後,回到第u個位置列舉第u位上的所有方案,此時回溯。

class

solution

//列舉每個位置上的備選數字

for(

int i =

0; i < nums.

size()

; i ++)}

} vectorint>

>

permute

(vector<

int>

& _nums)

};

搜尋順序:

將相同的元素都集中到一起,在填充位置時保證相同元素的相對位置不變。所以上一題dfs是對填充的位置進行搜尋,對填充位置的陣列元素進行列舉,本題dfs為保證相同元素的相對位置不變,對陣列元素依次進行搜尋,對存放陣列的位置進行列舉。如果下乙個遞迴的元素等於上乙個遞迴的元素,則下乙個遞迴的元素只能放在當前元素存放位置的後面。

回溯:陣列中第u+1個數列舉完所有位置時進行回溯。

class

solution

//列舉能被填充的各個位置

for(

int i = t; i < nums.

size()

; i ++)}

} vectorint>

>

permuteunique

(vector<

int>

& _nums)

};

搜尋順序:

對陣列中的元素依次進行搜尋,對每乙個元素可能加入集合,也可能不加。

回溯:第u+1個元素的兩種情況列舉完後,回溯。

class

solution

//不放入,直接進入第u+1個位置

dfs(u +1)

;//將第u個位置上的元素放入子集

path.

push_back

(nums[u]);

dfs(u +1)

; path.

pop_back()

;}vectorint>

>

subsets

(vector<

int>

& _nums)

};

用二進位制數來表示第j位是否選擇加入子集

class

solution

return ans;}}

;

搜尋順序:

在上一題的基礎上推廣,對陣列中的元素依次進行搜尋,同乙個元素選擇0~k次(k為相同元素的數量)。

回溯:第u+1個元素選擇0~k次的所有情況列舉完後,回溯。

class

solution

int k =0;

while

(u+k size()

&& nums[u+k]

== nums[u]

) k++

;//列舉第u個元素選擇從0到k的不同情況

for(

int i =

0; i <= k; i ++

)//恢復現場

for(

int i =

0; i <= k; i ++

) path.

pop_back()

;}vectorint>

>

subsetswithdup

(vector<

int>

& _nums)

};

搜尋順序:

按位置搜尋,每乙個位置都可填入在0~9之內,並比前乙個數大的數。

回溯:下一位置列舉完所有可能數後回溯。

class

solution

else

if(kt > k || nt > n)

return

;for

(int i = t +

1; i <=

9; i ++)}

vectorint>

>

combinationsum3

(int _k,

int _n)

};

搜尋順序:

按行搜尋,列舉每一列上可能的元素。

回溯:下一行列舉完回溯。

class

solution

//列舉每列是否能放上皇后

for(

int y =

0; y < n; y ++)}

}int

totalnqueens

(int _n)

};

搜尋順序:

從左到右,從上到下依次搜尋。

回溯:如果下一次搜尋沒有解,回溯。

class

solution}}

else

return

dfs(x, y +

1, b)

;return

false;}

void

solvesudoku

(vectorchar

>

>

& board)

}dfs(0

,0, board);}

};

搜尋順序:

依次拼接正方形的每條邊。每條邊列舉木棒順序從長到短(木棒越長,dfs的分支越少,分支下的方案數就越多,剪枝的效果就越好。

剪枝:1、所有木棒長度的總和不是4的倍數或木棒不到4根。

2、如果當前木棒拼接失敗,則跳過接下來所有長度相同的木棒。

3、如果當前木棒拼接失敗,且是當前邊的第乙個,則直接剪掉當前分支。

4、如果當前木棒拼接失敗,且是當前邊的最後乙個,則直接剪掉當前分支。

class

solution

//拼接第u根木棒,當前長度為cur,從第start棵木棒開始選

bool

dfs(

int u,

int cur,

int start)

return

false;}

};

中階演算法 dfs 回溯(1)

其實我們在遞迴演算法的學習過程中已經認識到了很多遞迴的思想,而遞迴的思想和dfs是非常相似的,不同的是在dfs中一般需要乙個標記過程也就是回溯,這裡我們練習乙個類似dfs的遞迴題。從現在開始實現從遞迴向dfs 回溯的過渡。include include include include include...

雜湊表習題整理(1)

1.拉鍊法int h n e n ne n idx 向雜湊表中插入乙個數 void insert int x 在雜湊表中查詢某個數是否存在 bool find int x 開放定址法int h n 如果x在雜湊表中,返回x的下標 如果x不在雜湊表中,返回x應該插入的位置 intfind int x ...

動態規劃習題整理(1)

狀態表示 f i 表示以第 i 個元素結尾的所有連續子陣列的最大值。狀態轉移 f i max f i 1 0 nums i f i 可劃分為兩部分,以第 i 1個元素結尾的所有連續子陣列加上第i個元素,或者只選用第 i 個元素。答案為所有f i 中的最大值。優化 由於f i 在計算時只會用到f i ...