概述
LeetCode每日练习78
- 78.子集
- 第一种方法,回溯递归
- 思路二
- 思路三
- 相同的还有以下多种类似的问题
78.子集
子集问题,看到这种题,肯定是可以用DFS加递归可以做的。首先分析思路,这种类似于全排列的情况,并且顺序不同算一种的话,其实就只要递归遍历就可以了
第一种方法,回溯递归
这题其实就是类似于全排列的问题,显而易见的是顺利不同的组合算是一个,例如[1,2,3], [1,3,2] , 因为数组中的元素是排序且无重复的,因此只需要考虑在递归进入下一阶段的时候对输入的begin+1 就可以了
res= [[]]
for i in range(begin,k):
temp.append(nums[i])
res.append(temp.copy())
dfs(i+1,temp)
temp.pop()
这里的递归最重要的方法是 递归向前,若begin 进入的值为0,则下一步就是dfs(1,temp), 由于进入的时候加上了nums[i] 所以回溯的时候必须把之前的最后一个元素给pop() 掉
思路二
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
for i in range(len(nums)+1):
for tmp in itertools.combinations(nums, i):
res.append(tmp)
return res
思路三
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[]]
for i in nums:
res = res + [[i] + num for num in res]
return res
相同的还有以下多种类似的问题
这里先把相同的问题,子集II写出来
初始的版本,未使用剪枝,只是回溯递归
# 子集II
# 思路同样可以使用回溯递归方法
# 与子集I 不同的地方是此时数组内会有相同元素
k = len(nums)
res=[[]]
nums.sort()
def dfs(begin,temp,nums):
for i in range(begin,k):
temp.append(nums[i])
if temp not in res:
res.append(temp.copy())
dfs(i+1,temp,nums)
temp.pop()
dfs(0,[],nums)
return res
显然这样的方式速度并不快,于是就要思考如何在出现重复的情况下提前剪枝。
nums.sort()
self.res = []
self.backtrack([], 0, nums, 0)
return self.res
def backtrack(self, sol, index, nums, pre_used):
if index == len(nums):
self.res.append(sol)
return
if not (index > 0 and nums[index] == nums[index-1] and pre_used == 0):
pre_used = 1
self.backtrack(sol+[nums[index]], index+1, nums, pre_used)
pre_used = 0
self.backtrack(sol, index+1, nums, 0)
这里的剪枝去掉了对元素的去重判断,转而在出现重复之前做剪枝处理,节省空间开支
- 46全排列
- 47全排列II
- 子集II
- 第K个排列
- 复原IP地址
- 组合总和
- 组合总和2
- 组合总和3
- 组合
最后
以上就是鳗鱼万宝路为你收集整理的LeetCode每日一题(集合问题)78.子集的全部内容,希望文章能够帮你解决LeetCode每日一题(集合问题)78.子集所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复