1.组合
77.组合
递归+剪枝
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
result = []
path = []
def backtracking(n:int, k:int, startint:int):
if len(path)==k:
result.append(path.copy())
return
for i in range(startint, n-(k-len(path))+1+1):
path.append(i)
backtracking(n,k,i+1)
path.pop()
backtracking(n, k, 1)
return result
2.组合总和III
216.组合总和III
剪枝:for循环中范围值剪枝,sum大小剪枝
class Solution:
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
result = []
path = []
def backtracking(k:int, n:int, startint:int, sum:int):
if sum > n:
return
if len(path)==k:
if sum==n:
result.append(path.copy())
return
for i in range(startint,11-(k-len(path))):
path.append(i)
sum += i
backtracking(k, n, i+1, sum)
path.pop()
sum -= i
backtracking(k, n, 1, 0)
return result
3.电话号码的字母组合
17.电话号码的字母组合
回溯二叉树的宽度为每个数字对应字母的个数,深度为digits的长度。
class Solution:
def __init__(self) -> None:
self.path = ""
def letterCombinations(self, digits: str) -> List[str]:
if not digits: return []
result = []
dic = ["", "", "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
def backtracking(digits:str, startint:int):
if len(self.path)==len(digits):
result.append(self.path)
return
for i in range(len(dic[int(digits[startint])])):
self.path += dic[int(digits[startint])][i]
backtracking(digits,startint+1)
self.path = self.path[:-1]
backtracking(digits, 0)
return result
4.组合总和
39.组合总和
终止条件增加:sum>target即return
剪枝:sum+i > target则结束循环
注:candidates要排序
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
candidates = sorted(candidates)
result = []
path = []
def backtracking(candidates: List[int], target: int, sum:int, startint:int):
if sum > target: return
elif sum == target:
result.append(path.copy())
return
else:
for i in range(startint,len(candidates)):
if sum+candidates[i]>target: return
path.append(candidates[i])
sum += candidates[i]
backtracking(candidates, target,sum,i)
sum -= candidates[i]
path.pop()
backtracking(candidates, target, 0, 0)
return result
5.组合总和II
40.组合总和II
剪枝:利用used数组,剪去横枝(与前一相同的枝不要),保留竖枝
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
result = []
path = []
used = [0]*len(candidates)
def backtracking(candidates: List[int], target: int, sum:int, startint:int):
if sum > target: return
elif sum == target:
result.append(path.copy())
return
for i in range(startint, len(candidates)):
if sum+candidates[i]>target: return
if i>0 and used[i-1]==0 and candidates[i-1]==candidates[i]: continue
path.append(candidates[i])
sum += candidates[i]
used[i] = 1
backtracking(candidates, target, sum, i+1)
used[i] = 0
sum -= candidates[i]
path.pop()
backtracking(sorted(candidates), target, 0, 0)
return result
6.分割回文串
131.分割回文串
横向:目标串长度,i(startint+1:len(s)+1)
纵向:起始位置>=目标串长度
注:切片始末位置
class Solution:
def partition(self, s: str) -> List[List[str]]:
if not s: return []
result = []
path = []
def isPalindrome(s:str):
for i in range(int(len(s)/2)):
if s[i]!=s[len(s)-i-1]:
return False
return True
def backtracking(s:str, startint:int):
if startint>=len(s):
result.append(path.copy())
return
for i in range(startint+1,len(s)+1):
t = s[startint:i]
if isPalindrome(t):
path.append(t)
backtracking(s, i)
path.pop()
backtracking(s,0)
return result
6.复原IP地址
93.复原IP地址
横向:目标串长度(startint,len(s))超过3位数不合法
纵向:3(最后一段判断是否合法)
注:判断非法字符
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
if len(s) > 12: return []
result = []
def isvalid(s:str, start:int, end:int):
if start>=end: return False
if s[start]=='0' and (end-start)>1: return False
if not 0<=int(s[start:end])<=255: return False
return True
def backtracking(s:str, startint:int, path:str, flag:int):
if flag == 3:
if isvalid(s,startint,len(s)):
path += s[startint:]
result.append(path)
return
for i in range(startint,len(s)):
if isvalid(s,startint,i+1):
t = t = s[startint:i+1]
path = path + t + "."
backtracking(s,i+1,path,flag+1)
path = path[:-len(t)-1]
backtracking(s,0,"",0)
return result
7.子集
78.子集
每一个节点都添加,而不是叶子节点添加
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
result = []
path = []
def backtracking(nums: List[int], startint:int):
result.append(path.copy())
if startint==len(nums):
return
for i in range(startint, len(nums)):
path.append(nums[i])
backtracking(nums,i+1)
path.pop()
backtracking(nums,0)
return result