zoukankan      html  css  js  c++  java
  • LeetCode Notes_#22_括号生成

    LeetCode Notes_#22_括号生成

    Contents

    题目


    解答

    方法1:暴力递归

    给出括号对数n之后,就确定了括号组合的字符串长度必然是2n,我们可以通过暴力递归的方式,在2n个位置上放置'('或者')',得到所有的排列序列,然后逐个判断每个排列序列是否是正确的,将正确的排列序列加入到结果列表当中。

    class Solution {
        public List<String> generateParenthesis(int n) {
            List<String> combinations = new ArrayList<>();
            generateAll(new char[2*n], 0, combinations);
            return combinations;
        }
        
        public void generateAll(char[] current, int pos, List<String> result){
            //出口条件:pos指针指向current的末尾之后一个位置(末尾是current.length - 1)
            if(pos == current.length){
                if(valid(current)){
                    result.add(new String(current));
                }
            //递推过程:在current数组末尾位置添加'('或者')',然后进行递归调用,在下一个位置pos + 1继续添加'('或者')'
            //这个过程中并不考虑'('和')'之间的数量以及配对是否是正确的,而是在将整个字符串都生成后,才判断这个字符串是否是正确配对的
            }else{
                current[pos] = '(';
                generateAll(current, pos + 1, result);
                current[pos] = ')';
                generateAll(current, pos + 1, result);
            }
        }
        //验证一个排列序列是否正确
        public boolean valid(char[] current){
            int balance = 0;
            for(char c: current){
                if(c == '('){
                    balance++;
                }else{
                    balance--;
                }
                if(balance < 0){
                    return false;
                }
            }
            return balance == 0;
        }
    }

    复杂度分析

    时间复杂度:,排列序列一共有个,对于每个排列序列,调用valid()方法进行验证,其时间复杂度为
    空间复杂度:,递归栈的深度是2n层。

    方法2:回溯

    在暴力递归法当中,我们其实生成了很多无效的排列序列,但是都要等到最后才能判断出它们是无效的。更优的方法应该是在构造序列的时候,就进行剪枝,对于已经确认无效的序列,提前将其排除(剪枝)。
    回溯法里边的回溯,指的就是撤销选择这一过程,无论这一次选择的结果是不是正确的,我们都需要回溯回去,尝试其他的可能性。

    class Solution {
        public List<String> generateParenthesis(int n) {
            List<String> ans = new ArrayList<>();
            backtrack(ans, new StringBuilder(), 0, 0, n);
            return ans;
        }
    
        // left,right代表左括号,右括号出现的次数
        private void backtrack(List<String> ans, StringBuilder cur, int left, int right, int n){
            //出口条件:长度达到2n,可以保证结果是正确的,直接加入结果列表当中
            if(cur.length() == 2*n){
                ans.add(cur.toString());
                return;
            }
            //左括号数量<n,可以继续添加左括号
            if(left < n){
                cur.append('(');
                backtrack(ans, cur, left + 1, right, n);
                cur.deleteCharAt(cur.length() - 1);
            }
            //右括号的数量<左括号的数量,可以继续添加右括号
            if(right < left){
                cur.append(')');
                backtrack(ans, cur, left, right + 1, n);
                cur.deleteCharAt(cur.length() - 1);
            }
        }
    }

    复杂度分析


  • 相关阅读:
    Visual Studio 2008中文正式版
    属性控制类
    PowerDesigner11技巧
    OPENXML用法
    .net下载文件
    Merge Into 语句代替Insert/Update在Oracle中的应用实战
    PowerDesigner中使用vbscript访问对象进行批量操作
    转:SubSonic介绍和相关文章
    C# 多线程控制控件实例(例程简单,注释详细)
    学习SubSonic的笔记 Version 2.1
  • 原文地址:https://www.cnblogs.com/Howfars/p/13918012.html
Copyright © 2011-2022 走看看