22. 括号生成

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

  void DFS(int Left, int Right) {
    if (Left == 0 && Right == 0) {
      Result_.emplace_back(Current_);
      return;
    }

    if (Left != 0) {
      // Still can start new pair by using '('.
      Current_.push_back('(');
      DFS(Left - 1, Right);
      Current_.pop_back();
    }
    if (Left < Right) {
      // Must close the left paren by using ')'.
      Current_.push_back(')');
      DFS(Left, Right - 1);
      Current_.pop_back();
    }
  }

public:
  vector<string> generateParenthesis(int n) {
    DFS(n, n);
    return Result_;
  }
};

看起来回溯题也不全是46. 全排列这种模板题,虽然因为DFS递归的性质,不动点仍然是需要的,但是最重要的是判定何时应该进行搜索的谓词。

在本题当中,谓词其实比较明确,就是「左括号只要有余就可以开启,但是右括号不能先于左括号进行闭合」,所以才会有Left != 0和Left < Right这两个看上去不对称的谓词,而这种不对称性是因为我们是自左向右线性考察字符串的,这一点很有意思。