LeetCode_Array_78. Subsets 求集合的所有子集 (C++)

目录

1,题目描述

2,思路

思路一:按位对应法

思路二:递归(回溯)

3,代码【C++】

思路一:按位对应法

思路二:递归(回溯)

4,测试效果


1,题目描述

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:

Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2,思路

参考这位大神的文章@犀牛饲养员 【求一个集合的所有子集问题】

先鼓掌,后欣赏。hhhhhh

思路一:按位对应法

思路十分简单直接。

以{1,2,3}为例;

000-111分别对应{}-{1,2,3},0表示无,1表示有;

这样只需要将mark从000-111递增,每递增一次判断mark的所有位(二进制),若为1,则将nums中的对应位添加入temp中;

需要注意区分二进制与十进制的关系!

思路二:递归(回溯)

以{1,2,3}为例

这张图讲的很清楚了;

初始时为空集,判断是否将1添加入集合中,到达第一层;

再判断是否将2添加入集合中,到达第二层;

......

深度到达nums.size()时,说明原始集合中所有元素均判断过一遍,已得出全部结果;

具体实现,请看下方代码(思路比较清晰,就不再赘述了)

  • 注意使用递归的深度,并以此作为递归出口的判断依据;
  • 回溯的两种方法:一,对每个元素标记,到底后会根据标记判断是否将此元素加入结果集;二,利用栈的特点,先入栈,后出栈,可以达到同样的效果;

3,代码【C++】

思路一:按位对应法

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> ans;    
        int end = (1 << nums.size()) - 1; //例如1<<3=8(1000),7-1=6(111),正好与000-111对应

        vector<int> temp = {};  //临时的容器

        for(int mark = 0 ; mark <= end ; mark++){

            //此处为按位与 &,将每一位与mark进行测试 得出哪一位为1 就将其添加入temp
            for(int i = 0 ; i < nums.size() ; i++){
                if((mark & (1 << i)) != 0) temp.push_back(nums[i]); //注意优先级!
            }
            ans.push_back(temp);
            temp = {};  //记得清空!
        }

        return ans;
    }
};

思路二:递归(回溯)

我的代码:

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> ans;    
        vector<bool> tag(nums.size(),false);    //判断哪个元素存在
        getSubsets(nums, tag, 0, ans);

        return ans;
    }

    void getSubsets(vector<int> nums, vector<bool> tag, int depth, vector<vector<int>>& ans){

        //原始集合中所有元素均遍历一遍
        if(depth == nums.size()){
            vector<int> temp;
            for(int i = 0 ; i < tag.size() ; i++){
                if(tag[i] == true) temp.push_back(nums[i]);
            }
            ans.push_back(temp);
        }
        else{
            tag[depth] = true;
            getSubsets(nums, tag, depth+1, ans);
            tag[depth] = false;
            getSubsets(nums, tag, depth+1, ans);
        }
        
    }
};

大神的代码:

class Solution {
public:
    vector<vector<int>> ans;
    vector<int> tmp;
    void find(int dep, vector<int>& nums)
    {
        if(dep <= 0)
        {
            ans.push_back(tmp);
            return;
        }
        tmp.push_back(nums[dep - 1]);
        find(dep - 1, nums);
        tmp.pop_back();
        find(dep - 1, nums);
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        find(nums.size(), nums);
        return ans;
    }
};

这就是差距。。。

4,测试效果

emmm,测试不是很准确,仅供参考

思路一:

思路二:

我的代码:

大神的代码:

发布了45 篇原创文章 · 获赞 5 · 访问量 2203

猜你喜欢

转载自blog.csdn.net/qq_41528502/article/details/104162599