leetcode22. 括号生成

leetcode22. 括号生成

题目:给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

分枝限界法。 其实就是一个dfs的递归树
由于字符串只有左括号和右括号两种字符,而且最终结果必定是左括号3个,右括号3个,所以我们定义两个变量left和right分别表示剩余左右括号的个数

  1. 如果在某次递归时,剩余的左括号的个数大于剩余右括号的个数,说明此时生成的字符串中右括号的个数大于左括号的个数,即会出现'())'这样的非法串,所以这种情况直接返回,不继续处理。这是递归出口1
    往下肯定不满足 这是递归树的减枝

  2. 如果left和right都为0,则说明此时生成的字符串已有3个左括号和3个右括号,且字符串合法,则存入结果中后返回。递归出口2

  3. 如果以上两种情况都不满足,若此时left大于0,则调用递归函数,注意参数的更新,若right大于0,则调用递归函数,同样要更新参数。代码如下:

c++版: 递归

	vector<string> generateParenthesis(int n) {
        vector<string> ans;
        dg(ans, "", n, n);
        return ans;
	}

    void dg(vector<string> &ans, string s, int left, int right) {
        if (left > right) return;  // 保证新加入( 或 ) 时,字符串还是匹配的
        if (left == right && left == 0) {
            ans.push_back(s);
            return;
        }
        if (left > 0)
            dg(ans, s + "(", left - 1, right);
        if (right > 0)
            dg(ans, s + ")", left, right - 1);
	}

Java 版:

和上面区别主要在用stringbuilder类型 path 存路径
这样在递归之前改变path的值 递归之后删除递归前append的字符 回溯
c++代码里直接传入临时变量 所以 不用回溯删除 没有影响

	public List<String> generateParenthesis(int n) {
        List<String> ans = new ArrayList<>();
        if (n < 1) return ans;
        StringBuilder path = new StringBuilder();
        helper(ans, path, n, n);
        return ans;
    }
    void helper(List<String> ans, StringBuilder path, int left, int right) {
        if (left > right) return;
        if (left == right && left == 0) {
            ans.add(path.toString());
            return;
        }

        if (left > 0) {
            path.append('(');
            helper(ans, path, left - 1, right);
            path.deleteCharAt(path.length() - 1);
        }
        if (right > 0) {
            path.append(')');
            helper(ans, path, left, right - 1);
            path.deleteCharAt(path.length() - 1);
        }
    }

版权声明:本文为qq_43778308原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。