78. 子集

class Solution {
  vector<vector<int>> Result_;
  vector<int> Current_;

  void DFS(vector<int>& V, int i) {
    if (i == V.size()) {
      Result_.emplace_back(Current_);
      return;
    }
    
    // The case of adding nums[i] into Current_.
    Current_.emplace_back(V[i]);
    DFS(V, i + 1);
    Current_.pop_back();

    // The case of NOT adding nums[i] into Current_. In fact, backtracking
    // allows we WRITE things sequentially, but EXECUTE without side effects.
    DFS(V, i + 1);
  }
public:
  vector<vector<int>> subsets(vector<int>& nums) {
    DFS(nums, 0);
    return Result_;
  }
};

回溯的关键在于,虽然我们写的代码好像是顺序执行,但是由于有回溯机制的存在,这些被回溯分隔开来的代码实际上是互不干扰的、不受副作用影响的。从22. 括号生成当中就能明显地看出来这个情况。

也正因如此,很多时候我们是不一定需要一个Visited_[]数组来记录访问情况的。很多时候用DFS参数记录就可以。