需要找陣列中數字的組合或排列
回溯法
res =
tmp =
if<
1.設定條件:把需要的當前列表加入res>
:return res
for 選擇 in 選擇列表:
<
2.做選
<
3.遞迴調 backtrack(選擇列表,當前列表,res)
<
4.撤銷選
給定乙個沒有重複數字的序列,返回其所有可能的全排列。
示例:input: [1,3,5]
output: [1,3,5], [1,5,3], [3,1,5], [3,5,1], [5,1,3], [5,3,1]
解題思路:結合回溯法的模式,需要特別考慮的是:
《滿足條件》到達底層的條件就是選擇列表nums為空
def
permute
(self, nums: list[
int])-
> list[list[
int]]:
# 函式輸入為空時的特殊情況
ifnot nums:
return nums
# 引數賦值初始化
res =
tmp =
# 呼叫backtrack函式,在類(class solution)中要用self呼叫函式
self.backtrack(nums, tmp, res)
return res
defbacktrack
(self, nums, tmp, res)
:# nums是選擇列表,tmp是當前選擇
#《滿足條件》 到達底層的條件就是選擇列表nums為空
ifnot nums::]
)for i in
range
(len
(nums)):
)# # nums[0:i] + nums[i+1:]就是把選了的nums[i]去掉,更新選擇列表nums
self.backtrack(nums[
0:i]
+ nums[i+1:
], tmp, res)
# 《撤銷選擇》 上面的呼叫結束即從下一層回溯到這一層,這時要更新當前選擇tmp
tmp.pop(
)
leetcode 78 (medium)給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集(冪集)。
示例:input: [1, 5, 3]
output: , [1], [5], [3], [1,5], [1,3], [5,3], [1,5,3]
方法一:回溯法,遞迴
解題思路結合回溯法模式,需要特別考慮的是:
《滿足條件》因為所有出現的當前列表都是子集,不用設定條件,把所有tmp加到res中
不能從選擇列表中取所有元素,因為找子集只考慮當前元素之後的元素們,不能出現重複元素,所以要設起始點idx排除用過的元素,idx影響的是range的範圍(選擇列表)。遞迴呼叫時,因為 nums 不包含重複元素,並且每乙個元素只能使用一次,所以下一次搜尋從 i + 1 開始。
class
solution
:def
subsets
(self, nums: list[
int])-
> list[list[
int]]:
ifnot nums:
return
none
res =
self.backtrack(nums,
, res,0)
return res
defbacktrack
(self, nums, tmp, res, idx)::
])# 只考慮當前元素之後的元素們,要設起始點排除用過的元素
for i in
range
(idx,
len(nums)):
# 《做選擇》
)# 《遞迴呼叫》
# 因為 nums 不包含重複元素,並且每乙個元素只能使用一次,所以下一次搜尋從 i + 1 開始
self.backtrack(nums, tmp, res, i+1)
# 《撤銷選擇》
方法二:迭代
def
subsets
(nums)
: res =
)# 大迴圈,取出陣列內的每個元素
for i in nums:
#for j in res: #不要直接迴圈列表,用索引迴圈
# 小迴圈,取出結果的每個索引
for j in
range
(len
(res)):
a =list
(res[j]
)return res
leetcode 77 (medium)給定兩個整數 n 和 k,返回 1 … n 中所有可能的 k 個數的組合。
輸入: n = 4, k = 2
輸出: [[2,4], [3,4], [2,3], [1,2], [1,3], [1,4]]
解題思路:
畫出n叉樹分析
k 限制了樹的高度,n 限制了樹的寬度,想到k作為《滿足條件》,n用來建立《選擇列表》
跟子集一樣,這裡用過的元素不能再出現,要在range選擇列表中設定起始點idx排除已經用過的元素
class
solution
:def
combine
(self, n:
int, k:
int)
-> list[list[
int]]:
ifnot n or
not k:
return
none
nums =
range(1
, n+1)
res =
self.backtrack(nums,
, res, k,0)
return res
defbacktrack
(self, nums, tmp, res, k, idx)
:# 《滿足條件》 k限制樹的高度,達到高度時加上當前列表tmp
iflen
(tmp)
== k::]
)# 參考子集的做法,設定起始點idx用來排除已經用過的元素
for i in
range
(idx,
len(nums)):
# 《做選擇》
)# 《遞迴呼叫》
self.backtrack(nums, tmp, res, k, i+1)
# 《撤銷選擇》
tmp.pop(
)
在框架基礎上的一點優化,直接用n限制寬度
class
solution
:def
combine
(self, n:
int, k:
int)
-> list[list[
int]]:
ifnot n or
not k:
return
none
res =
self.backtrack(n,
, res, k,1)
return res
defbacktrack
(self, n, tmp, res, k, idx):if
len(tmp)
== k::]
)# 優化**:不用設nums,n就是nums的索引
for i in
range
(idx, n+1)
: self.backtrack(n, tmp, res, k, i+1)
tmp.pop(
)
參考
labuladong的演算法小抄
演算法和資料結構
演算法和資料結構 演算法和資料結構 千絲萬縷的聯絡 縱觀各種演算法書籍,大多都是將演算法和資料結構作為乙個整體來講述。資料結構就是陣列 樹結構等儲存或表現物件資料的結構。將演算法和資料結構作為整體講述,是因為必須依照演算法中的常用操作選擇資料結構。例如,事先將資料儲存在適當的樹形結構中,大多數情況下...
演算法和資料結構
演算法 資料結構與演算法的關係是相互依賴不可分割的。演算法的定義 演算法是解決特定問題求解步驟的描述,在計算機中為指令的有限序列,並且每條指令表示乙個或多個操作。演算法的特性 有窮性 確定性 可行性 輸入 輸出。演算法設計的要求 正確性 可讀性 健壯性 高效率和低儲存量需求。演算法特性與演算法設計容...
演算法和資料結構
好吧,在這裡,您被優秀或優秀的軟體開發人員所隔開。在這種情況下,我會告訴您,一開始或至少在我的情況下,我知道大多數時候,對於我認識的大多數人,您會覺得自己是乙個無能的人或白痴。基本上,我怎麼可能不理解這一點,然後您會感到沮喪。在這種情況下,我會告訴您情況並不像您想的那麼糟糕,您會告訴我 您知道,您甚...