题目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],
[]
]
代码1:
Recursive (Backtracking)
class Solution {
public:
void subsets(vector<int> &nums, int start, vector<int>& sub, vector<vector<int>>& subs)
{
subs.push_back(sub);
for (int i = start; i < nums.size(); i++) {
sub.push_back(nums[i]);
cout << "before : ";
/*在全排序中是subsets(nums, start+1, sub, subs)这种形式,而这种形式在这题中答案不对,而本代码中的形式在全排列中也不对*/
subsets(nums, i + 1, sub, subs);
sub.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> subs;
vector<int> sub;
subsets(nums, 0, sub, subs);
return subs;
}
};
错误代码:
class Solution {
public:
void subsets(vector<int> nums, int start, vector<int>& sub, vector<vector<int>>& subs)
{
subs.push_back(sub);
for (int i = start; i < nums.size(); i++) {
sub.push_back(nums[i]);
subsets(nums, i + 1, sub, subs);
}
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> subs;
vector<int> sub;
subsets(nums, 0, sub, subs);
return subs;
}
};
此代码注意和全排列代码区分,在第二种全排列中nums加引用是错误的,不加引用是对的,而在道题中,nums加引用是正确的,不加引用的错误的,目前还不知道为什么?
代码2:
Iterative
Using [1, 2, 3]
as an example, the iterative process is like:
- Initially:
[[]]
- Adding the first number to all the existed subsets:
[[], [1]]
; - Adding the second number to all the existed subsets:
[[], [1], [2], [1, 2]]
; - Adding the third number to all the existed subsets:
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
.
The code is as follows.
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> subs(1, vector<int>());
for (int i = 0; i < nums.size(); i++) {
int n = subs.size();
for (int j = 0; j < n; j++) {
subs.push_back(subs[j]);
subs.back().push_back(nums[i]);
}
}
return subs;
}
};
代码3:
Bit Manipulation
To give all the possible subsets, we just need to exhaust all the possible combinations of the numbers. And each number has only two possibilities: either in or not in a subset. And this can be represented using a bit.
Using [1, 2, 3]
as an example, 1
appears once in every two consecutive subsets, 2
appears twice in every four consecutive subsets, and 3
appears four times in every eight subsets (initially all subsets are empty):
[], [], [], [], [], [], [], []
[], [1], [], [1], [], [1], [], [1]
[], [1], [2], [1, 2], [], [1], [2], [1, 2]
[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]
The code is as follows.
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
int n = pow(2, nums.size());
vector<vector<int>> subs(n, vector<int>());
for (int i = 0; i < nums.size(); i++) {
for (int j = 0; j < n; j++) {
if ((j >> i) & 1) {
subs[j].push_back(nums[i]);
}
}
}
return subs;
}
};
题目2:
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
Example:
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
代码:
class Solution {
public:
void subsets(vector<int>& nums, vector<vector<int> >& res, vector<int> &temp, int start, int len)
{
res.push_back(temp);
for(int i = start; i < len; ++i)
{
if(i > start && nums[i] == nums[i-1])
continue;
temp.push_back(nums[i]);
/*
cout << "before : ";
for (auto num : temp)
cout << num << " ";
cout << endl;
*/
subsets(nums, res, temp, i + 1, len);
/*
cout << "before : ";
for (auto num : temp)
cout << num << " ";
cout << endl;
*/
temp.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> res;
int len = nums.size();
sort(nums.begin(), nums.end());
vector<int> temp;
subsets(nums, res, temp, 0, len);
return res;
}
};
示例:
Input: [1,2,2]
结果输出:
图中那一行空行,就代表空。
错误代码:
class Solution {
public:
void subsets(vector<int> nums, vector<vector<int> >& res, vector<int> &temp, int start, int len)
{
res.push_back(temp);
for(int i = start; i < len; ++i)
{
if(i > start && nums[i] == nums[i-1])
continue;
temp.push_back(nums[i]);
/*
cout << "before : ";
for (auto num : temp)
cout << num << " ";
cout << endl;
*/
subsets(nums, res, temp, i + 1, len);
/*
cout << "before : ";
for (auto num : temp)
cout << num << " ";
cout << endl;
*/
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> res;
int len = nums.size();
sort(nums.begin(), nums.end());
vector<int> temp;
subsets(nums, res, temp, 0, len);
return res;
}
};
此代码注意和全排列代码区分,在第二种全排列中nums加引用是错误的,不加引用是对的,而在道题中,nums加引用是正确的,不加引用的错误的,目前还不知道为什么?
示例:
Input: [1,2,2]
结果输出:
说明递归返回时,nums的值并没有返回到上一个值。
下面是全排列的两种情况代码:
题目1:
Given a collection of distinct integers, return all possible permutations.
Example:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
代码1:
class Solution {
public:
void permuteHelp(vector<int> &nums, vector<vector<int> > &res, int k, int len)
{
if(k == len)
{
res.push_back(nums);
return;
}
for(int i = k; i < len; ++i)
{
swap(nums[i], nums[k]);
permuteHelp(nums, res, k + 1, len);//如果将k+1改成i+1,答案不对
swap(nums[i], nums[k]);
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> res;
int len = nums.size();
if(len == 0)
return res;
permuteHelp(nums, res, 0, len);
return res;
}
};
代码2:
class Solution {
public:
void permuteHelp(vector<int> nums, vector<vector<int> > &res, int k, int len)
{
if(k == len)
{
res.push_back(nums);
return;
}
for(int i = k; i < len; ++i)
{
swap(nums[i], nums[k]);
permuteHelp(nums, res, k + 1, len);
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> res;
int len = nums.size();
if(len == 0)
return res;
permuteHelp(nums, res, 0, len);
return res;
}
};
上面两个代码答案都正确,nums加引用和不加引用都正确。
题目2:
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
Example:
Input: [1,1,2]
Output:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
正确代码:
class Solution {
public:
void permuteUniqueHelp(vector<int> nums, vector<vector<int> > &res, int k, int len)
{
if(k == len-1)
{
res.push_back(nums);
return;
}
for(int i = k; i < len; ++i)
{
if(i != k && nums[i] == nums[k])
continue;
swap(nums[i], nums[k]);
permuteUniqueHelp(nums, res, k + 1, len);
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> res;
int len = nums.size();
if(len == 0)
return res;
sort(nums.begin(), nums.end());
permuteUniqueHelp(nums, res, 0, len);
return res;
}
};
错误代码:
class Solution {
public:
void permuteUniqueHelp(vector<int> &nums, vector<vector<int> > &res, int k, int len)
{
if(k == len-1)
{
res.push_back(nums);
return;
}
for(int i = k; i < len; ++i)
{
if(i != k && nums[i] == nums[k])
continue;
swap(nums[i], nums[k]);
//cout << "before" << nums[i] <<";" <<nums[k] << endl;
permuteUniqueHelp(nums, res, k + 1, len);
//cout <<"after" << nums[i] << ";" << nums[k] << endl;
/*和上一个代码的区别:nums加引用,下面加一行代码*/
swap(nums[i], nums[k]);
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> res;
int len = nums.size();
if(len == 0)
return res;
sort(nums.begin(), nums.end());
permuteUniqueHelp(nums, res, 0, len);
return res;
}
};
这题的两种代码和第一题的两种代码是对应,在这种情况下nums加引用就不对了。而调试时,after和before栈顶元素一一对应的,目前不清楚这种方法为啥不对!