LeetCode回溯問題 多問題總結

2021-10-10 10:51:30 字數 3389 閱讀 3342

給定乙個無重複元素的陣列 candidates 和乙個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

candidates 中的數字可以無限制重複被選取。

說明:所有數字(包括 target)都是正整數。

解集不能包含重複的組合。

示例 1:

輸入:candidates = [2,3,6,7], target = 7,

所求解集為:

[[7],

[2,2,3]

]

簡單的回溯

基本就是回溯的模板,注意點就是返回的arraylist不能作為引數放進方法中,因為每次回溯都會回到之前的狀態。

直接上**

class

solution

public

void

backstrace

(int

candidates,

int target,arraylist

temp,

int p)

if(target<0)

return

;for

(int i=p;i}

給定乙個陣列 candidates 和乙個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

candidates 中的每個數字在每個組合中只能使用一次。

說明:所有數字(包括目標數)都是正整數。

解集不能包含重複的組合。

示例 1:

輸入: candidates = [10,1,2,7,6,1,5], target = 8,

所求解集為:

[[1, 7],

[1, 2, 5],

[2, 6],

[1, 1, 6]

]

思路

使用set天然的除重,但是**結構會比較複雜剪枝

注意到題目裡說的是「每個數字在每個組合使用一次」,意味著數值相同但不是同乙個的數字,可以在同乙個組合**現。即可以有[1,1,6]這種情況。不重複就需要按順序搜尋,在搜尋的過程中檢測分支是否會出現重複結果。注意:這裡的順序不僅僅指數組candidates有序,還指按照一定順序搜尋結果。

class

solution

public

void

backstrace

(int

candidates,

int target,arraylist

temp,

int p)

if(target<0)

return

;for

(int i=p;i}

總體的**和上一題差不多,關鍵是在剪枝的位置

if

(i>p&&candidates[i]

==candidates[i-1]

)continue

;

為什麼這麼寫可以刪除重複的。這裡借用leetcode上看到的解釋

這個避免重複當思想是在是太重要了。

這個方法最重要的作用是,可以讓同一層級,不出現相同的元素。即

1/ \

2 2 這種情況不會發生 但是卻允許了不同層級之間的重複即:

/ \

5 5例21

/2 這種情況確是允許的

/2

為何會有這種神奇的效果呢?

首先 cur-1 == cur 是用於判定當前元素是否和之前元素相同的語句。這個語句就能砍掉例1。

可是問題來了,如果把所有當前與之前乙個元素相同的都砍掉,那麼例二的情況也會消失。

因為當第二個2出現的時候,他就和前乙個2相同了。

那麼如何保留例2呢?

那麼就用cur > begin 來避免這種情況,你發現例1中的兩個2是處在同乙個層級上的,

例2的兩個2是處在不同層級上的。

在乙個for迴圈中,所有被遍歷到的數都是屬於乙個層級的。我們要讓乙個層級中,

必須出現且只出現乙個2,那麼就放過第乙個出現重複的2,但不放過後面出現的2。

第乙個出現的2的特點就是 cur == begin. 第二個出現的2 特點是cur > begin.

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

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

輸出:[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

思路

基本的回溯,用乙個標誌陣列用來除重。

class

solution

public

void

backstrace

(list

> res,arraylist

temp,

int nums,

boolean label)

for(

int i=

0;i}}

給定乙個可包含重複數字的序列 nums ,按任意順序 返回所有不重複的全排列。

示例 1:

輸入:nums = [1,1,2]

輸出:[[1,1,2],

[1,2,1],

[2,1,1]]

思路

與上一題不同的地方在於給的陣列中有重複元素,

用set去重,只需增加一步用set去重

class

solution

}

2.剪枝,思想與40一樣,允許下乙個,不允許自身

class

solution

public

void

backstrace

(list

> res,arraylist

temp,

int nums,

boolean label)

for(

int i=

0;i}

注意這裡的

if

(i>

0&&label[i-1]

==false

&&nums[i]

==nums[i-1]

)continue

label[i-1]==false的作用為判斷是否在同一層,若在同一層則去除,為下一層則保留。

很多問題1

1054 猴子吃桃 1056 幸運數字 1059 最高分 時間限制 1 sec 記憶體限制 128 mb 輸入x,計算上面公式的前10項和。輸入乙個實數x。輸出乙個實數,即數列的前10項和,結果保留3位小數。0.841 include include include intmain printf 3...

leetcode 子集問題(回溯演算法)

給你乙個整數陣列 nums 陣列中的元素 互不相同 返回該陣列所有可能的子集 冪集 解集不能包含重複的子集。你可以按 任意順序 返回解集。示例 1 輸入 nums 1,2,3 輸出 1 2 1,2 3 1,3 2,3 1,2,3 示例 2 輸入 nums 0 輸出 0 解決子集問題最常用的方法就是回...

leetcode 遞迴 回溯問題 總結

注意 整體思路清晰,回溯的過程大概是怎樣的 每層遞迴實際上要解決的問題是什麼 一定記住,該重置的狀態要重置,因為回溯就是相當於在每一層的遞迴中做選擇,選擇了不同的選項,在遇到阻礙或者達到條件結束遞迴之後,再想嘗試其他的選擇路徑,應當記住回退到之前的狀態。縱向 遞迴的深度,完整地解決問題 搜尋完所有的...