力扣---子集---回溯(子集型回溯)---递归

 递归法思路:

首先考虑为什么能用递归(因为存在大问题和小问题之间的关系,大问题:从第 i 个数字到最后一个数字之间找子集,小问题:从第 i+1 个数字到最后一个数字之间找子集)。其次,用递归的三段式:写边界条件(i==n+1,也就是所有的数都被判断完毕),考虑第 i 个数,不考虑第 i 个数。

代码:

C++:

class Solution {
public:
    void insert(vector<vector<int>>& res,vector<int>& visit,int len,vector<int>& nums){
        vector<int> temp;
        for(int i=0;i<len;i++){
            if(visit[i]){
                temp.push_back(nums[i]);
            }
        }
        res.push_back(temp);
    }

    void dfs(int i,vector<vector<int>>& res,vector<int>& visit,int len,vector<int>& nums){
        
        //边界条件
        if(i==len){
            insert(res,visit,len,nums);
            return;
        }
        
        //选择当前数字
        visit[i]=1;
        dfs(i+1,res,visit,len,nums);
        visit[i]=0;

        //不选择当前数字
        dfs(i+1,res,visit,len,nums);
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        int len=nums.size();
        vector<int> visit(len,0);
        vector<vector<int>> res;
        dfs(0,res,visit,len,nums);
        return res;
    }
};

Python:

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        len_nums=len(nums)
        visit=[0]*len_nums
        res=[]

        def insert():
            temp=[]
            for i in range(len_nums):
                if visit[i]:
                    temp.append(nums[i])
            res.append(temp)

        def dfs(i):
            if i==len_nums:
                insert()
                return

            visit[i]=1
            dfs(i+1)
            visit[i]=0

            dfs(i+1)

        dfs(0)
        return res 


二进制法求解思路:

主要思路就是用二进制来帮助选择元素,拿第一个例子来说,0(000)就是三个元素都没有选择,即[ ];1(001)就是选择了第三个元素,即[3]。所以我们只需要遍历0-2^{n}-1(2^{n}:1<<n)即可。如果当下遍历到了6(110,这里记为 i ),那么该怎么获取第几个元素被选择了呢,就依次判别 i & (1<< j ),j 的范围是0-len(nums),如果 i 的第 j 位为1,那么说明第 j 位被选择,同时 i & (1<< j )不为0,该位被记录。

代码:


C++:

class Solution {
public:
    vector<int> g;
    vector<vector<int>> res;
    vector<vector<int>> subsets(vector<int>& nums) {
        //用二进制来帮助元素选择(0-2^len)
        int len=nums.size();
        int temp=1<<len;
        for(int i=0;i<temp;i++){
            g.clear();
            for(int j=0;j<len;j++){
                if(i & (1<<j)){
                    g.push_back(nums[j]);
                }
            }
            res.push_back(g);
        }
        return res;
    }
};

Python:

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        g=[]
        res=[]
        len_nums=len(nums)
        temp=1<<len_nums
        for i in range(temp):
            g.clear()
            for j in range(len_nums):
                if i&(1<<j):
                    g.append(nums[j])
            res.append(g.copy())
        return res

注意这句话:

res.append(g.copy())

res.append(g)
#当您将 g 添加到 res 中时,您实际上是在添加对 g 的引用,而不是它的一个副本。因此,当您清空 g 或者之后对 g 做任何修改时,res 中已经添加的那些 g 的引用也会反映这些修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值