leetcode78 子集 c++

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

三种想法:

1.动态规划;

2.深度遍历所以组合;

3.深度遍历取或者不取;

说明:解集不能包含重复的子集。

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

1.思路动态规划:对于nums = [1, 2, 3]。可以这样考虑,

1).由nums = [] 的子集推出 nums=[1]的子集

2).由nums = [1] 的子集推出 nums=[1, 2]的子集

...

而状态转移就是在原来的子集上添加新加入的这个元素

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> temp;
        res.push_back(temp);//初始化
        for(int i=0; i<nums.size(); i++)
        {
            int st = res.size();
            for(int j=0; j<st; j++)
            {
                temp = res[j];
                temp.push_back(nums[i]);
                res.push_back(temp);
            }
        }
        return res;
    }
};

2.回溯遍历,找到所有的可能组合

class Solution {
public:
    void dfs(vector<vector<int>> &res, vector<int> &temp, vector<int> &nums, int k)
    {
        res.push_back(temp);
        for(int i=k; i<nums.size(); i++)
        {
            temp.push_back(nums[i]);
            dfs(res, temp, nums, i+1);
            temp.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> temp;
        dfs(res, temp, nums, 0);
        return res;
    }
};

最后回溯8ms, 动态规划16ms。。。想想原因。。

原来是再给temp数组赋值的时候很费时间,修改了一下代码动态规划也只要8ms了

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        // vector<int> temp;
        // res.push_back(temp);
        res.push_back(vector<int>{});
        for(int i=0; i<nums.size(); i++)
        {
            int st = res.size();
            for(int j=0; j<st; j++)
            {
                //temp = res[j];//这一步很费时间
                //temp.push_back(nums[i]);
                res.push_back(res[j]);
                res[st+j].push_back(nums[i]);
            }
        }
        return res;
    }
};

3.深度遍历,对每一个数取或者不取

void dfs2(vector<int> &nums, vector<int> &temp, int k)
{
    if (k == nums.size())
    {
        printV(temp);
        return;
    }
    temp.push_back(nums[k]);
    dfs2(nums, temp, k + 1);
    temp.pop_back();
    dfs2(nums, temp, k + 1);
}

其实2和3都是把所有组合列举了出来。3很直观可以看出复杂度是2的n次方;2的话复杂度是所有组合数之和,根据二项式定理其实也就是2的n次方;1的话是每次元素比之前多一倍也就是1,2,4,8....也是2的n次方

最后2和3对比了一下:

#include <bits/stdc++.h>

using namespace std;
void printV(vector<int> &nums)
{
    for (auto t : nums)
        cout << t << " ";
    cout << endl;
}

void dfs1(vector<int> &nums, vector<int> &temp, int k)
{
    //求所有组合
    printV(temp);
    if (k == nums.size())
    {
        return;
    }
    for (int i = k; i < nums.size(); i++)
    {
        temp.push_back(nums[i]);
        dfs1(nums, temp, i + 1);
        temp.pop_back();
    }
}

void dfs2(vector<int> &nums, vector<int> &temp, int k)
{
    //每次选或者不选
    if (k == nums.size())
    {
        printV(temp);
        return;
    }
    temp.push_back(nums[k]);
    dfs2(nums, temp, k + 1);
    temp.pop_back();
    dfs2(nums, temp, k + 1);
}

int main()
{
    vector<int> nums = {1, 2, 3, 4};
    vector<int> temp;
    dfs1(nums, temp, 0);
    cout << "=========================" << endl;
    dfs2(nums, temp, 0);
    return 0;
}

输出结果:

1
1 2
1 2 3
1 2 3 4
1 2 4
1 3
1 3 4
1 4
2
2 3
2 3 4
2 4
3
3 4
4
=========================
1 2 3 4
1 2 3
1 2 4
1 2
1 3 4
1 3
1 4
1
2 3 4
2 3
2 4
2
3 4
3
4
发布了15 篇原创文章 · 获赞 18 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/zhangruijerry/article/details/99430917