演算法46--回溯法3--Combination Sum1,2,3,4
Given a set of candidate numbers (candidates
) (without duplicates) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
The same repeated number may be chosen from candidates
unlimited number of times.
Note:
- All numbers (including
target
- The solution set must not contain duplicate combinations.
Example 2:Input: candidates = [2,3,5],
target = 8, A solution set is: [ [2,2,2,2], [2,3,3], [3,5] ]
假設符合條件的集合長度為N,首先考慮第一位,第一位可以取值nums所有元素,統計r中已有元素的和,
當s==target時記錄此時r,返回即可,
當s>target返回即可
否則說明s<target 則應繼續尋找下一個元素,使用start來標識當前已經到那個數字作為最終結果的開始尋找點。
以2, 3, 6, 7為例,第一個數字可以取2,3,6,7
第一個數字取2時,第二個數字 2, 3, 6, 7
第一個數字取3時,第二個數字 3, 6, 7 如果第二個數字從第一個數字開始取,則會產生重複,因此應該從第二個數字開始取。
class Solution: def combinationSum(self, candidates, target): """ :type candidates: List[int] :type target: int :rtype: List[List[int]] """ rr=[] candidates.sort() self.backtrace(rr, [], 0, candidates, target, 0) return rr def backtrace(self, rr, r, s, candidates, target, start): if s==target: rr.append(r.copy()) return if s>target: return for i in range(start, len(candidates)): r.append(candidates[i]) s += candidates[i] self.backtrace(rr, r, s, candidates, target, i) s -= candidates[i] r.pop(-1)
Given a collection of candidate numbers (candidates
) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
Each number in candidates
may only be used once in the combination.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:Input: candidates = [10,1,2,7,6,1,5]
, target = 8
, A solution set is: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
每個數字只能用一次,將陣列升序排列,這樣相同的數字便會相鄰,r中存放所有可能的試探組合
考慮第一位數字,可以放入陣列所有數字,然後依據s與target來進行判斷
若s<target 考慮第二位數字,首先若i>start and nums[i-1]==nums[i]說明r中已經取過nums[i-1]的值,因此nums[i]可以直接跳過,否則會重複,進行下一次遍歷從start+1開始,每一個數字只能用一次,依次不能繼續從start開始。
class Solution:
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
rr=[]
candidates.sort()
self.backtrace(rr, [], 0, candidates, target, 0)
return rr
def backtrace(self, rr, r, s, candidates, target, start):
if s == target:
rr.append(r.copy())
return
if s > target:
return
for i in range(start, len(candidates)):
if i>start and candidates[i-1]==candidates[i]:
continue
r.append(candidates[i])
#print(r)
s += candidates[i]
#print(s)
self.backtrace(rr, r, s, candidates, target, i+1)
r.pop(-1)
s -= candidates[i]
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
Note:
- All numbers will be positive integers.
- The solution set must not contain duplicate combinations.
Example 1:Input: k = 3, n = 7 Output: [[1,2,4]]
回溯法 最終集合長度為k,和為7 考慮第一位取值範圍 1--9 當第一位確定時,第二位的取值是除去第一位的1--9剩餘數字
遍歷順序
1 12 123 1234 12345 .... 8 89 9
回溯法提供了對於集合的某種遍歷順序,每取一種組合方式,都要對於該種取值集合進行判斷是否符合條件,符合直接儲存返回,若已超出臨界條件並且繼續考慮下一位肯定不符合條件則直接返回,如果條件達不到則進行下一位的考慮,增加集合r的取值,進行遞迴判斷。
class Solution:
def combinationSum3(self, k, n):
"""
:type k: int
:type n: int
:rtype: List[List[int]]
"""
rr=[]
self.backtrace(rr, [], 0, k, 1, n)
return rr
def backtrace(self, rr, r, s, k, start, n):
if len(r)==k and s==n:
rr.append(r.copy())
return
for i in range(start, 10):
r.append(i)
s += i
#print(r, i, s)
self.backtrace(rr, r, s, k, i+1, n)
r.pop(-1)
s -= i
優化如下:加入提前終止條件:
class Solution:
def combinationSum3(self, k, n):
"""
:type k: int
:type n: int
:rtype: List[List[int]]
"""
rr=[]
self.backtrace(rr, [], 0, k, 1, n)
return rr
def backtrace(self, rr, r, s, k, start, n):
if len(r)==k and s==n:
rr.append(r.copy())
return
if s>n:
return
if len(r)>k:
return
if len(r)==k and s!=n:
return
for i in range(start, 10):
r.append(i)
s += i
#print(r, i, s)
self.backtrace(rr, r, s, k, i+1, n)
r.pop(-1)
s -= i
劍指offer回溯法題目總結
回溯法總結