总结
  • 深搜时候给足限制条件
  • 博客来源:LawsonAbs@CSDN
思想

这题不像简单的全排列,还是有那么一丢丢的思考在里面。主要考察的点有两个:

  • 如何写递归完成搜索的过程?
  • 如何控制不重复的采样?在不使用set的情况下。
  • 如何获取各个长度的子集?

第一个问题很好解决,就类似于全排列,直接挨个遍历即可。
第二个问题是关键:如何保证挨个遍历的时候,不重复?如果完全按照全排列,肯定会重,如先获取了[1,2,3],接着又访问了[1,3,2],那么怎么解决呢?我们可以在深搜的时候给一个下标阈值,用于限定只能在这个范围内采样,这样当搜索到[1,3]中的3时,因为2的下标小于3,不会再往前寻找了。这时候遍历就结束了。
第三个问题同样也比较好解决,一个集合的子集长度分别从0 到 n,所以每次遍历的时候,我们限制一下获取的集合的长度即可。

综上所述,可得如下代码:

代码
from copy import copy
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = [[]]
        if len(nums) == 0:
            return res 
        
        # 子集的长度,从0 到 n 
        # 怎么避免重复?当前的这个数搞过了,就再也不会被遍历
        for all_len in range(1,len(nums)):
            vis = [0] * len(nums)            
            for i in range(len(nums)): # 每个数都有组成长度为 all_len 的资格
                vis[i] = 1
                cur = [] # 当前此次循环的
                cur.append(nums[i])
                self.dfs(nums,res,cur,all_len,vis,i+1)
        res.append(copy(nums))
        return res

    # start 表示搜索的起始下标
    def dfs(self,nums,res,cur,all_len,vis,start):
        if len(cur) == all_len:
            res.append(copy(cur))
            return 
        for i in range(start,len(nums)):
            if vis[i] == 0:
                vis[i] = 1
                cur.append(nums[i])
                self.dfs(nums,res,cur,all_len,vis,i+1)
                cur.pop()
                vis[i] = 0