1.回溯法求解排列组合问题的基本框架如下图,根据具体问题的不同会有一定的改动,但是大体都是遵循choose--explore--unchoose的过程。
2.组合问题
给定无重复数组[1,2,3],返回该数组元素所有的子集[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
ans = []
self.subsetshelper([],nums,0,ans)
return ans
def subsetshelper(self,prefix,nums,start,ans):
ans.append(prefix[:])
if start==len(nums):
return
for i in range(start,len(nums)):
prefix.append(nums[i])
self.subsetshelper(prefix,nums,i+1,ans)
prefix.pop()
给定有重复元素的数组[1,2,2],返回该数组元素的子集[[],[1],[2],[1,2],[1,2,2]]
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if not nums:
return []
nums.sort()
ans = []
self.subsetsWithDupHelper([],nums,0,ans)
return ans
def subsetsWithDupHelper(self,prefix,nums,start,ans):
ans.append(prefix[:])
if start==len(nums):
return
for i in range(start,len(nums)):
if i>start and nums[i]==nums[i-1]:#remove duplicates
continue
prefix.append(nums[i])
self.subsetsWithDupHelper(prefix,nums,i+1,ans)
prefix.pop()
3.排列问题
无重复数组,返回其所有的排列
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if not nums:
return []
ans = []
self.permutehelper([],nums,ans)
return ans
def permutehelper(self,prefix,nums,ans):
if len(prefix)==len(nums):
ans.append(prefix[:])
return
for i in range(len(nums)):
if nums[i] in prefix:
continue
prefix.append(nums[i])
self.permutehelper(prefix,nums,ans)
prefix.pop()
有重复数组,返回其所有排列
class Solution(object):
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if not nums:
return []
ans = []
nums.sort()
self.permuteUniqueHelper([],nums,[False]*len(nums),ans)
return ans
def permuteUniqueHelper(self,prefix,nums,used,ans):
if len(prefix)==len(nums):
ans.append(prefix[:])
else:
for i in range(len(nums)):
if used[i] or i>0 and nums[i]==nums[i-1] and not used[i-1]:
continue
used[i] = True
prefix.append(nums[i])
self.permuteUniqueHelper(prefix,nums,used,ans)
prefix.pop()
used[i] = False
4.组合问题的变形
给定无重复数组,数组元素可以无限次利用,求数组和为指定值的数组子集
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
if not candidates or target<=0:
return []
ans = []
self.combinationSumHelper([],candidates,0,target,ans)
return ans
def combinationSumHelper(self,prefix,nums,start,target,ans):
if target<0:
return
elif target==0:
ans.append(prefix[:])
return
else:
for i in range(start,len(nums)):
prefix.append(nums[i])
self.combinationSumHelper(prefix,nums,i,target-nums[i],ans)
prefix.pop()
给定有重复数组,求数组和为指定值的数组子集
class Solution(object):
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
if not candidates or target<=0:
return []
candidates.sort()
ans = []
self.combinationSum2Helper([],candidates,0,target,ans)
return ans
def combinationSum2Helper(self,prefix,nums,start,target,ans):
if target<0:
return
elif target==0:
ans.append(prefix[:])
else:
for i in range(start,len(nums)):
if i>start and nums[i]==nums[i-1]:
continue
prefix.append(nums[i])
self.combinationSum2Helper(prefix,nums,i+1,target-nums[i],ans)
prefix.pop()
leetcode 131 parlindrome partitioning
将给定字符串分割成若干个回文子字符串
class Solution(object):
def partition(self, s):
"""
:type s: str
:rtype: List[List[str]]
"""
if not s:
return []
ans = []
self.partitionHelper([],s,0,ans)
return ans
def partitionHelper(self,substrs,s,start,ans):
if start==len(s):
ans.append(substrs[:])
else:
for i in range(start,len(s)):
if not self.ispalin(s,start,i):
continue
else:
substrs.append(s[start:i+1])
self.partitionHelper(substrs,s,i+1,ans)
substrs.pop()
def ispalin(self,s,start,end):
while start<=end:
if s[start]!=s[end]:
return False
start +=1
end -=1
return True
分割数组下标相当于组合问题
排列问题:给定N,K,求出所有大小为k的元素取值在1-N的数组
class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
if n<k or n<=0 or k<=0:
return []
ans = []
self.combineHelper([],n,1,k,ans)
return ans
def combineHelper(self,prefix,n,start,k,ans):
if len(prefix)==k:
ans.append(prefix[:])
elif start==n+1:
return
else:
for i in range(start,n+1):
prefix.append(i)
self.combineHelper(prefix,n,i+1,k,ans)
prefix.pop()