回溯算法团灭子集、组合、排列问题
根据元素是否重复和是否可复选,分为以下三种变体:
1、元素无重不可复选
2、元素有重不可复选
3、元素无重可复选
该篇给出第一种情况的代码,另外两种的实现见上方变体链接。
class NoRepeatAndSingle:"""元素无重不可复选"""def subsets(self, nums: List[int]) -> List[List[int]]:"""子集问题:param nums::return:"""self.res = []self.track = []self.s_backtrack(nums, 0)return self.resdef s_backtrack(self, nums, start):# 前序位置,每个节点的值都是⼀个⼦集self.res.append(self.track[:])for i in range(start, len(nums)):# 做选择self.track.append(nums[i])# 通过 start 参数控制树枝的遍历,避免产⽣重复的⼦集self.s_backtrack(nums, i+1)# 撤销选择self.track.pop()def combination(self, nums: List[int], k: int) -> List[List[int]]:"""组合问题:param nums::param k::return:"""self.res = []self.track = []self.c_backtrack(nums, 0, k)return self.resdef c_backtrack(self, nums, start, k):# base caseif len(self.track) == k:self.res.append(self.track[:])returnfor i in range(start, len(nums)):# 做选择self.track.append(nums[i])# 通过 start 参数控制树枝的遍历,避免产⽣重复的⼦集self.c_backtrack(nums, i+1, k)# 撤销选择self.track.pop()def permute(self, nums: List[int]) -> List[List[int]]:"""排列问题:param nums::return:"""self.res = []self.track = []self.used = [False] * len(nums)self.p_backtrack(nums)return self.resdef p_backtrack(self, nums):# base caseif len(self.track) == len(nums):self.res.append(self.track[:])returnfor i in range(0, len(nums)):# 已经存在 track 中的元素,不能重复选择if self.used[i]:continue# 做选择self.used[i] = Trueself.track.append(nums[i])# 通过 start 参数控制树枝的遍历,避免产⽣重复的⼦集self.p_backtrack(nums)# 撤销选择self.used[i] = Falseself.track.pop()