生活随笔
收集整理的這篇文章主要介紹了
【Leetcode】组合、排列、子集、切割(回溯模板和去重方法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
基礎版回溯函數參數只有(target, show),target是目標大小,show是遞歸傳遞的變量。
- 一個數字只能用一次,那下次遞歸時就把這次用去掉 nums[:i]+nums[i+1:]
- [1,2,3]和[3,2,1]算重復,那么加入索引,每次都往后找
- 要求組合長度為k,那就放個變量 count 計數
- 如果候選列表有重復的話,先排序,再前后兩個進行判斷
class Solution:def combinationSum3(self
, k
: int, n
: int) -> List
[List
[int]]:nums
= [1,2,3,4,5,6,7,8,9,1,2]nums
.sort
()res
= []def backtrack(target
, show
, nums
, idx
, count
):if target
== 0 and count
== k
:res
.append
(show
[:])returnif target
< 0 or count
> k
:returnfor i
in range(idx
, len(nums
)):if i
>idx
and nums
[i
] == nums
[i
-1]:continuebacktrack
(target
-nums
[i
], show
+[nums
[i
]], nums
[:i
]+nums
[i
+1:], i
, count
+1)return res
return backtrack
(n
, [], nums
, 0, 0)
上面這套模板可以做排列,組合和子集問題。
如果是切割問題的話,用下面的模板:
每次改變的是切割的起始點 idx,原字符串 s 并沒有改變。
class Solution:def partition(self
, s
: str) -> List
[List
[str]]:def isvalid(s
):i
= 0j
= len(s
)-1while i
< j
:if s
[i
] != s
[j
]:return Falsei
+= 1j
-= 1return Trueres
= []path
= []def backtrack(s
, idx
):if idx
==len(s
):res
.append
(path
[:])returnfor i
in range(idx
, len(s
)):if isvalid
(s
[idx
:i
+1]):path
.append
(s
[idx
:i
+1])backtrack
(s
,i
+1)path
.pop
()return res
return backtrack
(s
,0)
下面的遞增子序列類似于子集問題,需要注意
- 單向尋找,回溯時取nums[i+1:]
- 不能排序,所以哈希去重
- 判斷相鄰元素的大小時的邊界問題
class Solution:def findSubsequences(self
, nums
: List
[int]) -> List
[List
[int]]:res
= []def backtrack(nums
, path
):ht
= {}if len(path
)>1:res
.append
(path
[:])for i
in range(len(nums
)):if len(path
)>0:if nums
[i
]<path
[-1]:continueif nums
[i
] in ht
:continueht
[nums
[i
]] = ibacktrack
(nums
[i
+1:], path
+[nums
[i
]])return res
return backtrack
(nums
, [])
猜你喜歡:👇🏻
?【Leetcode】背包問題模板
?【Leetcode】幾種簡單的排序算法
?【Leetcode】二分法左側邊界右側邊界模板
總結
以上是生活随笔為你收集整理的【Leetcode】组合、排列、子集、切割(回溯模板和去重方法)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。