回溯
回溯和dfs关系密切
DFS基本思想:
- 本质是遍历决策树
- 关注路径、选择列表、结束条件
- 结合回溯:重点是撤销选择
res = []
def dfs(路径, 选择列表):
if 满足结束条件:
res.append(路径)
return
for 选择 in 选择列表:
做选择
dfs(路径, 选择列表)
撤销选择
全排列
注意res.append(path[:]):是path的一个拷贝
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
def dfs(depth,size,path,seen):
if depth==size:
res.append(path[:])
for i in range(size):
if not seen[i]:
seen[i]=1
path.append(nums[i])
dfs(depth+1,size,path,seen)
seen[i]=0
path.pop()
size=len(nums)
seen=[0]*size
res=[]
dfs(0,size,[],seen)
return res
注意,这里当
if depth==size:
时没有return
,虽然下面的for函数即使运行,也会因为seen[i]=1
,而不会对结果造成影响,但这是很不好的习惯最好在dfs结束时,加上
return
其实也可以用内置的permutations
函数:
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res=[list(t)for t in permutations(nums)]
return res
电话号码的字母组合
选择列表为:dic[str(digits[depth])]
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
dic={'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']}
res=[]
def dfs(depth,size,path,seen):
if depth==size:
res.append(''.join(path[:]))
return
for i in dic[str(digits[depth])]:
seen[i]=1
path.append(i)
dfs(depth+1,size,path,seen)
seen[i]=0
path.pop()
seen=defaultdict(int)
size=len(digits)
if not size:return []
dfs(0,size,[],seen)
return res
括号生成
当左括号不多于n时,可以添加左括号
当左括号数量大于右括号时,可以添加右括号
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
def dfs(depth,path,cnt):
if depth==2*n:
if cnt==0:res.append(''.join(path[:]))
return
for x in ('(',')'):
if x=='(' and cnt>=n:continue
if x==')' and cnt<=0:continue
path.append(x)
if x=='(':
cnt+=1
else:
cnt-=1
dfs(depth+1,path,cnt)
if x=='(':
cnt-=1
else:
cnt+=1
path.pop()
res=[]
dfs(0,[],0)
return res
组合总和
since list is an unhashable type, we use Counter to remove duplication
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res=[]
def dfs(sum,path):
if sum==target:
flag=True
for r in res:
if len(r)==len(path):
if Counter(r)==Counter(path):
flag=False
break
if flag:res.append(path[:])
return
if sum>target:return
for c in candidates:
path.append(c)
dfs(sum+c,path)
path.pop()
dfs(0,[])
return res