给定一组不含重复元素的整数数组 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