问题
思路
按照层次进行枚举即可。主要剪枝的条件。
1. 当前元素之前不能出现过
2. 必须是升序
注意状态恢复。
代码
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ret;
vector<int> arr;
ret.push_back(arr);
set<int> visited;
int sz = nums.size();
if(!sz) return ret;
dfs( arr, visited, nums, sz, ret );
return ret;
}
private:
void dfs( vector<int>& arr, set<int>& visited, vector<int>& nums, int n, vector<vector<int>>& ret ){
if( arr.size() == n ) return;
else{
for(int i = 0; i < n; ++i){
if( visited.find(nums[i]) != visited.end() ) continue;
int sz = arr.size();
bool legal = true;
for(int k = 0; k < sz; ++k){
if( arr[k] >= nums[i] ){
legal = false;
break;
}
}
if(!legal) continue;
arr.push_back(nums[i]);
visited.insert(nums[i]);
ret.push_back(arr);
dfs( arr, visited, nums, n, ret );
arr.pop_back(); // 状态恢复
visited.erase( nums[i] ); // 状态恢复
}
}
}
};
后记
判断一个数组是否可以两分,正解应该在这里。
背包看起来好像可以解决,但是由于背包要求的是不超过V的条件下,最大的价值。所以它没法精确。
看一道题目:
在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]
注意事项
你不可以将物品进行切割。
注意这到题目,这到题目其实并不是标准的背包。此时,它的容量和价值一样。所以,问你在给定V的条件下,最多装多满。此时,价值和容量一样。
如果有4个物品[2, 3, 5, 7]
如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。
如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。
函数需要返回最多能装满的空间大小。
这个题目也可以换个问法:
对于数组[2,3,5,7],如果不超过11,数组中挑出几个数所能形成的最大值应该是多少。
当然,可以采用上面的办法,枚举所有子集,把小于11的拿出来。比以下最大值。
背包的思想也可以使用,在不超过容量11的前提下。获取的最大价值。此时,价值和容量的值是一样的。
但是,如果问数组是否可以等分。以上面的题目为例,那就是是否可以找到一个子集,它的和为8.5。如果是背包,只能用容量做上限。没法精确,这就是问题。
代码2
改进了visted用下标进行标记。
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> arr;
vector<vector<int>> ret;
ret.push_back(arr);
set<int> visited;
dfs( arr, visited, nums, nums.size(), ret );
return ret;
}
private:
void dfs(vector<int>& arr, set<int>& visited, vector<int>& nums, int n, vector<vector<int>>& ret ){
if( arr.size() == n ) return;
else{
for(int i = 0; i < n; ++i){
if( visited.find(i) != visited.end() ) continue;
int sz = arr.size();
bool flag = true;
for( int k = 0; k < sz; ++k ){
if( arr[k] > nums[i] ){ flag = false; break; }
}
if(!flag) continue;
arr.push_back( nums[i] );
visited.insert( i );
ret.push_back(arr);
dfs( arr, visited, nums, n, ret );
arr.pop_back();
visited.erase(i);
}
}
}
};