Leetcode 78 子集
题目:
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
- 1 <= nums.length <= 10
- -10 <= nums[i] <= 10
- nums 中的所有元素 互不相同
算法思想:
采用回溯算法。首先要明确的是,本题与之前采用回溯算法的本质不同是,符合要求的答案在每个节点上,而之前的问题符合要求的答案在叶子节点上,这一点是明显的不同,但是总体思路和收集节点的方式是相同的。
- 回溯函数模板返回值以及参数
path:记录当前路径上的节点
result:记录所有满足条件的组合
startIndex:访问过的元素在下一层递归的时候不在访问 - 回溯函数终止条件
本题其实可以没有结束条件,因为for循环中自带结束条件。如果有结束条件也是可以的,即startIndex大于或等于索要遍历元素的集合的长度。 - 单层搜索逻辑
- path中加入节点
- 递归加入下一个节点
- path中出栈
代码实现:
class Solution:
def subsets(self, nums):
result = []
path = []
# result.append([])
self.backtracking(nums, 0, path, result)
return result
def backtracking(self, nums, startIndex, path, result):
result.append(path[:]) # 收集子集,要放在终止添加的上面,否则会漏掉自己
# if startIndex >= len(nums): # 终止条件可以不加
# return
for i in range(startIndex, len(nums)):
path.append(nums[i])
# result.append(path[:]) # 当然本题收集节点可以放在递归前
self.backtracking(nums, i + 1, path, result)
path.pop()
Leetcode 90 子集2
题目:
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
- 1 <= nums.length <= 10
- -10 <= nums[i] <= 10
算法思想:
依然采用回溯算法。本题与子集最大的差别就是可以有重复元素,因此本题涉及到剪枝。
大体思路与子集相同。但在实现上最大的不同在于,要设置used数组,记录哪些元素被访问过。
因此,借助used数组来实现剪枝。那么问题来了,如何剪枝?首先要清楚的是,如例子中,两个2是否可以出现在答案中,根据例子看,是可以的。那么答案中的两个2怎么来的?肯定不是同一个位置上的2,那么这两个2分别是第一个位置上的2和第二个位置上的2,所以这样的情况是不重复的。其次,什么情况下重复呢?比如,第一个元素取1, 第二个元素取2。这种情况就包含了第一个元素取2的所有情况,仔细想是不是这个道理?答案是 是的。因此这里就涉及到剪枝的情况。
代码实现:
class Solution:
def subsetsWithDup(self, nums):
path = []
result = []
nums.sort()
used = [0] * len(nums)
startIndex = 0
result.append([])
self.backtracing(nums, startIndex, used, path, result)
return result
def backtracing(self, nums, startIndex, used, path, result):
for i in range(startIndex, len(nums)):
if i > 0 and nums[i-1] == nums[i] and used[i-1] == 0:
continue
else:
path.append(nums[i])
used[i] = 1
result.append(copy.deepcopy(path))
self.backtracing(nums, i+1, used, path, result)
path.pop()
used[i] = 0
return result