1. 子集
78. subsets
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
方法
回溯法, 循環內遞歸, 即DFS
https://pic.leetcode-cn.com/a4f4acf7177b6a1131b1ef5da97c1dae218f3c34e9418219055c729c90300122-image.png
求子集就是在遞歸生成一棵樹, 一條一條路徑、一個一個節點
遍歷, 當前路徑path增加了各個可能元素後, 再遞歸考慮下個元素
下個元素的取值範圍很重要
"""
result = []
def backtrack(path, idx):
result.append(path)
for i in range(idx, len(nums)):
backtrack(path+[nums[i]], i+1)
backtrack([], 0)
return result
2. 全排列
46. permutations
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
方法
回溯法, DFS
遍歷一棵樹, 類似於求所有子集那道題
https://pic.leetcode-cn.com/9d228e7ee9c0beceb48983717e253fd0cd6ba96ef76d06758451a1d4af651c36-image.png
"""
result = []
def backtrack(path):
if len(path) == len(nums):
result.append(path)
return
for num in set(nums) - set(path):
backtrack(path+[num])
backtrack([])
return result
3. 括號生成
22. generate-parentheses
class Solution(object):
def generateParenthesis(self, n):
"""
:type n: int
:rtype: List[str]
方法
生成潛在的可能結果排列組合, 然後一個一個排除
排除的過程可以使用輔助棧
"""
def judge_valid(parenthesis):
stack = []
for char in parenthesis:
if char == '(':
stack.append(char)
else:
if not stack:
return False
stack.pop()
return True if not stack else False
result = []
def backtrack(path):
if len(path) == 2*n:
if judge_valid(''.join(path)):
result.append(''.join(path))
return
if path.count('(') < n:
backtrack(path+['('])
if path.count(')') < n:
backtrack(path+[')'])
backtrack([])
return result
4. 組合總和
39. combination-sum
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
思路
排列組合, 回溯時限制和不能大於target, 當等於target時輸出
"""
def backtrack(path, cur_sum):
if path and cur_sum == target:
path.sort()
if str(path) not in tmp_set:
result.append(path)
tmp_set.add(str(path))
elif path and cur_sum > target:
return
for candidate in candidates:
backtrack(path+[candidate], cur_sum+candidate)
result = []
tmp_set = set()
backtrack([], 0)
return result