【回溯】【leetcode】打印n对括号的所有合法组合

题目:

括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。

说明:解集不能包含重复的子集。

例如,给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

来源:

面试题 08.09. 括号

22. 括号生成

解题思路:回溯

定义2个变量left和right,left记录放置'('的数量,right记录放置')'的数量。

  • 递归终止条件:左括号必定先放完,所以右括号放完时结束
  • 递归调用条件:根据left和right当前情况,判断下一个字符的可能情况
public:
    vector<string> result;
    string path;
    vector<string> generateParenthesis(int n) {
        back(n, 0, 0);
        return result;
    }

    void back(int n, int left, int right) {
        if (right == n) {
            // 返回结果
            result.push_back(path);
            return;
        }
        // 找出所有可能情况
        char cand[2];
        int sz = 0;
        if (left < n) {
            cand[sz++] = '(';
        }
        if (left > right) {
            cand[sz++] = ')';
        }
        // 处理每种可能情况
        for (int i = 0; i < sz; i++) {
            path.push_back(cand[i]);
            if (cand[i] == '(')
                back(n, left+1, right);
            else 
                back(n, left, right+1);
            path.resize(path.size() - 1);
        }
    }
};

另一种思路,代码相比简洁,如下:

两个变量,left记录左括号剩余数量,right记录右括号剩余数量。可能情况有2种:

  1. 左括号,当有剩余时处理
  2. 右括号,当左括号有剩余,并且左括号剩余少时。
class Solution {
public:
    vector<string> result;
    string path;
    vector<string> generateParenthesis(int n) {
        back(n, n);
        return result;
    }
    // left记录左括号剩余数量,right记录右括号剩余数量
    void back(int left, int right) {
        if (left == 0 && right == 0) {
            result.push_back(path);
            return;
        }
        // 无非2种可能情况
        if (left > 0) {
            // 情况1
            path.push_back('(');
            back(left-1, right);
            path.resize(path.size() - 1);
        }
        if (left < right && right > 0) {
            // 情况2
            path.push_back(')');
            back(left, right - 1);
            path.resize(path.size() - 1);
        }
    }
};

猜你喜欢

转载自blog.csdn.net/hbuxiaoshe/article/details/115218160