题目要求

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, given n = 3, a solution set is:

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

即生成成对的括号,其中括号的数量为n

思路和代码

这题还是一道典型的在前一种情况的前提下生成当前的情况(backtracking)。这样的题目往往需要通过递归的方式来间接记录当前的情况。
类似的题目还包括

我们只需要确保即将生成的结果中右括号的数量不会超过左括号即可。当右括号和左括号的剩余量均为0时,及为一个最终结果。如果左右括号的剩余量还未达到0,则将继续添加左括号或是右括号直到左右括号剩余量为0。
代码如下:

    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<String>();
        if(n<=0){
            return result;
        }
        generateParenthesis(result, "(", n-1, n);
        return result;
        
    }
    
    private void generateParenthesis(List<String> result, String current, int leftRemainCount, int rightRemainCount){
        if(leftRemainCount==0){
            while(rightRemainCount-->0){
                current += ")";
            }
            result.add(current);
            return;
        }
        generateParenthesis(result, current+"(", leftRemainCount-1, rightRemainCount);
        if(rightRemainCount>leftRemainCount){
            generateParenthesis(result, current+")", leftRemainCount, rightRemainCount-1);
        }
    }

利用StringBuilder简单优化

String和StringBuilder的最大区别在于,对String的任何修改都会生成一个新的String对象,并将当前的String指针指向该新生成的对象。在字符串修改频繁的场景下可能会带来大量的内存浪费。而StringBuilder则会在直接原来的对象上进行修改,其指针仍然指向原来的对象。因此在递归的过程中使用StringBuilder一定要注意,对StringBuilder对象的修改不要相互干扰。
代码如下:

    public List<String> generateParenthesis2(int n) {
        List<String> rst = new ArrayList<>();
        if(n == 0) {
          return rst;     
        }
        backtracking(rst, new StringBuilder(), n, n);
        return rst;
    }
    private void backtracking(List<String> rst, StringBuilder sb, int left, int right) {
        if(left > right) {
          return;    
        }
        if(left > 0) {
          sb.append('(');
          backtracking(rst, sb, left - 1, right);
          sb.setLength(sb.length() - 1);
        }
        if(right > 0) {
          sb.append(')');
          backtracking(rst, sb, left, right - 1);
          sb.setLength(sb.length() - 1);
        }
        
        if(left == 0 && right == 0) {
          rst.add(sb.toString());  
        }
    }

clipboard.png
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~


raledong
2.7k 声望2k 粉丝

心怀远方,负重前行