0

I want to enumerate all possible subsets of a given array, which should be 2^N in total. Here I use sum to represent all subsets since sums are distinct in this example. I use a auxiliary array called taken to mark if the current item is taken and do a DFS. Here is the code:

void dfs(vector<int>& res, vector<int>& nums, vector<bool>& taken, int sum, int pos) {
    for (int i = pos; i < nums.size(); ++i) {
        if (!taken[i]) {
            taken[i] = true;
            res.push_back(nums[i] + sum);
            dfs(res, nums, taken, sum + nums[i], pos + 1);
            taken[i] = false;
        }
    }
    return;
}
int main() {
    vector<int> test = {1, 10, 100, 1000};
    vector<bool> t(4, false);
    vector<int> res;
    dfs(res, test, t, 0, 0);
    return 0;
}

But this code does not return 2^n results in result.

ssd
  • 83
  • 6
  • _"However, it is not correct. Can someone help?"_ Isn't a valid question. What isn't correct specifically? Compile time errors, runtime errors or unexpected output (for which specific input)? In other words post a [MCVE] please, instead of letting us guess. – user0042 Oct 17 '17 at 00:01
  • what is the intended output BTW? – thebenman Oct 17 '17 at 00:15
  • @thebenman results are put into vector res. I checked it already. – ssd Oct 17 '17 at 00:17
  • The actual results should be 2^N - 1 in this case since "none" is not pushed into results. I used an array to store visited information, which is not really necessary. At first I made up this problem just to test the idea of using an array to remember paths in DFS. – ssd Oct 17 '17 at 01:37

2 Answers2

2

I have fixed your code

void dfs(vector<int>& res, vector<int>& nums,  int sum, int pos) {

    for (int i = pos; i < nums.size(); ++i) {
        res.push_back(sum + nums[i]);
        dfs(res, nums,  sum + nums[i], i + 1); // i + 1 instead of pos + 1
    }
    return;
}
int main() {
    vector<int> test = {1, 2, 3};
    vector<int> res;
    dfs(res,test,0, 0);
    cout << res.size() << endl;
    copy(res.begin(), res.end(), ostream_iterator<int>(cout , " "));
    cout <<endl;
    return 0;
} 

And since you do not visit the elements backwards (i.e. already added indexes) you do not have to maintain an array to check for visited.

thebenman
  • 1,621
  • 14
  • 35
1
void enumerate_all_subsets(vector <int> &res, const vector <int> &nums) {
    if(nums.empty()) return;
    for(auto i = 0ull; i < (1 << nums.size()); ++ i) {
        int sum = 0;
        for(auto k = 0; k < nums.size(); ++ k)
            if((i >> k) & 1)
                sum += nums[k];
        res.push_back(sum);
    }
}

This iterates over a vector of a size up to size 63 (if your unsigned long longs are 64 bit). Any larger vectors should probably be rethought as that would take a while as this is O(2^n), as you noted.

Basically each bit of the unsigned long long i represents a position in nums and if it should be added to the sum or not.

N00byEdge
  • 1,106
  • 7
  • 18