好久没写,仍然是模版方法
思路简述:递归调用
看到 全排列,或者 枚举全部解,等类似的 搜索枚举类型题,基本就是 回溯 没跑了。
def backtrack(State,判断条件):
if 满足什么条件就可以将State加入到res:
res.append(S)
return
if 怎么怎么:
backtrack(State,条件变化)
res =[]
backtrack(初始状态)
return res
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
def backtrack(S,left,right):
if left + right == 2 * n:
res.append(S)
return
if left < n :
backtrack(S + "(" , left+1 , right)
if right < left:
backtrack(S + ")" , left , right+1)
res = []
backtrack("",0,0)
return res
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
phone={
"2":['a','b','c'],
"3":['d','e','f'],
"4":['g','h','i'],
"5":['j','k','l'],
"6":['m','n','o'],
"7":['p','q','r','s'],
"8":['t','u','v'],
"9":['w','x','y','z']
}
if len(digits) == 0:
return []
def Backtrack(component,ss):
if len(ss) == 0:
res.append(component)
return
for i in phone[ss[0]]:
Backtrack(component+i,ss[1:])
res = []
Backtrack("",digits)
return res
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
def backtrack(S,q,k):
if k == 0 :
res.append(S)
return
for i in range(q,n+1):
backtrack(S+[i],i+1,k-1)
res = []
backtrack([],1,k)
return res
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
def backtrack(s,ns):
for i,j in enumerate(ns):
backtrack(s+[j],ns[i+1:])
if len(s) <= n:
res.append(s)
return
res = []
backtrack([],nums)
return res
46. 全排列
知识点有一个是复制的话直接等号改变新的会覆盖旧的,用[:]切片的话不会更改旧的
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
def backtrack(S,ns):
for i,j in enumerate(ns):
cp = ns[:]
cp.remove(j)
print(S,j,cp)
backtrack(S+[j],cp)
if len(S) == n:
res.append(S)
return
res = []
backtrack([],nums)
return res
47. 全排列 II
!开始剪纸,剪纸就是continue,发现递归想从代码里面理解是很容易绕进去的,但是从逻辑解释还是可以通的,这边加一个check,和sort
剪纸条件是没有重复出现+该元素跟上一个元素相同且上一个元素未使用
每一个backtrack是一条枝,节点访问完之后就要把访问标记恢复成0,为了下次回溯
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
check = [0 for i in range(n)]
nums.sort()
def backtrack(S,k):
if k == 0:
res.append(S)
return
for i,j in enumerate(nums):
if i > 0 and nums[i] == nums [i-1] and check[i-1] == 0:
continue
if check[i] == 1:
continue
check[i] = 1
backtrack(S+[j],k-1)
check[i] = 0
res = []
backtrack([],n)
return res
39. 组合总和
这个题解的时候慢了些,要理解第一次调用是[]连接candidates,而不是从第一个candidates开始画
数组添加元素可以直接用+[],而不使用append
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def backtrack(S,k,candidates):
if k == target:
res.append(S)
return
if k > target:
return
for i,j in enumerate(candidates):
backtrack(S+[j], k+j,candidates[i:])
res = []
S = []
backtrack(S,0,candidates)
return res
解释
40. 组合总和 II
两种写法
1.相对位置
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
n = len(candidates)
candidates.sort()
def backtrack(S,k,can,p):
if k == target:
res.append(S)
return
if k > target:
return
for i,j in enumerate(can):
if i > 0 and can[i] == can[i-1] :
continue
backtrack(S+[j],k+j,can[i+1:],p+1)
res = []
backtrack([],0,candidates,0)
return res
2.绝对位置
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
n = len(candidates)
candidates.sort()
def backtrack(S,k,begin):
if k == target:
res.append(S)
return
if k > target:
return
for i in range(begin,n):
if i > begin and candidates[i] == candidates[i-1] :
continue
backtrack(S+[candidates[i]],k+candidates[i],i+1)
res = []
backtrack([],0,0)
return res
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
def backtrack(S,ns):
res.append(S)
for i,j in enumerate(ns):
if i > 0 and ns[i] == ns [i-1]:
continue
backtrack(S+[j],ns[i+1:])
res = []
backtrack([],nums)
return res
401. 二进制手表
用回溯还是费点脑子的,candidate就很妙,把它改成组合总和了,非常棒这个题解思路,也学到了一下%格式控制
class Solution:
def readBinaryWatch(self, turnedOn: int) -> List[str]:
hours = [8,4,2,1,0,0,0,0,0,0]
minus = [0,0,0,0,32,16,8,4,2,1]
def backtrack(k,index,hour,minu):
if k == 0 :
if hour < 12 and minu < 60:
res.append('%d:%02d' % (hour, minu))
return
return
for i in range(index,10):
backtrack(k-1,i+1,hour+hours[i],minu+minus[i])
res = []
backtrack(turnedOn,0,0,0)
return res
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
ans = []
def backtrack(S,s):
if len(S)== 4:
if not s:
ans.append(".".join(S))
return
for i in range(1,len(s)+1):
if 0< int (s[:i]) <= 255 and s[0] != '0' or s[:i] == '0':
backtrack(S+[s[:i]],s[i:])
else:
return
backtrack([],s)
return ans