演算法和資料結構(Python) 回溯法求排列組合

2021-10-03 03:16:24 字數 4328 閱讀 9494

需要找陣列中數字的組合排列

回溯法

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的演算法小抄

演算法和資料結構

演算法和資料結構 演算法和資料結構 千絲萬縷的聯絡 縱觀各種演算法書籍,大多都是將演算法和資料結構作為乙個整體來講述。資料結構就是陣列 樹結構等儲存或表現物件資料的結構。將演算法和資料結構作為整體講述,是因為必須依照演算法中的常用操作選擇資料結構。例如,事先將資料儲存在適當的樹形結構中,大多數情況下...

演算法和資料結構

演算法 資料結構與演算法的關係是相互依賴不可分割的。演算法的定義 演算法是解決特定問題求解步驟的描述,在計算機中為指令的有限序列,並且每條指令表示乙個或多個操作。演算法的特性 有窮性 確定性 可行性 輸入 輸出。演算法設計的要求 正確性 可讀性 健壯性 高效率和低儲存量需求。演算法特性與演算法設計容...

演算法和資料結構

好吧,在這裡,您被優秀或優秀的軟體開發人員所隔開。在這種情況下,我會告訴您,一開始或至少在我的情況下,我知道大多數時候,對於我認識的大多數人,您會覺得自己是乙個無能的人或白痴。基本上,我怎麼可能不理解這一點,然後您會感到沮喪。在這種情況下,我會告訴您情況並不像您想的那麼糟糕,您會告訴我 您知道,您甚...