登录  /  注册
博主信息
博文 82
粉丝 0
评论 1
访问量 105143
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
22. Generate Parentheses--求n对括号组成可以组成的全部有效括号序列
子龙的博客搬家啦httpswwwcnblogscomZiLongZiLong
原创
1228人浏览过

描述:

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:

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

我的老实人+不择手段算法:

let cache = {};
var generateParenthesis = function(n) {
   暴力枚举
      if(n==1){
        return ['()'];
    }
    if(cache[n])
        return cache[n];
    let start = '',result = [];
    for(let i = 0; i < n; i++){
        start +='()';
    }
    result.push(start);
    for(let i = 1,l=start.length; i < n;i++){
        let move = generateParenthesis(start.slice(0,i*2).length /2),
            holdOn = generateParenthesis(start.slice(i*2).length/2);
            
        move.forEach((item)=>{
                holdOn.forEach((holdOn) => {
                    for( let j = 0,subLength = holdOn.length; j < subLength; j += 2){
                        result.push( holdOn.slice(0,j+1) + item + holdOn.slice(j+1) )
                    }
                })
            
        })
            
    }
    for(let i = 0,l=result.length; i < l; i++){
        if(result.indexOf(result[i])!==result.lastIndexOf(result[i])){
            result.splice(i,1);
            i--;
        }
    }
    cache[n] = result;
    return result;
 }

思路:给定n对括号,可以先构造一个模板,然后在这个模板中,通过移动左边1,2,...,n-1 个括号到右边的括号里面,这样就可以构造出所有可能的有效序列了,

比分说: n = 3, 那么我们可以先构造出一个模板 ()()(),而后通过移动左边的1,2个括号到右边的2,1个括号构成的序列的括号里边的位置,那么就可以构造出其他有效序列了,而这里边必须注意的是移动左边的括号往右边的括号里边放的时候,左右两个子序列也会有各自的排序方法,所以需要递归的先求出左右序列的所有排列可能,而后再进行插入操作。

事情还没完,这样左右两边都列出可能的排列之后,肯定会发生重复,所以最后我又进行了一个数组去重,真是不可原谅,最后提交的时候抛出了308ms惊人的成绩。这还是在用了cache缓存一定子序列的情况下跑的。

然后要着重贴一下官方的解答下面的一个递归算法,

var generateParenthesis = function(n) {
     /* 保持 左右平衡 */
    let result = [],
        
        produce = (curStr,left,right,curNums) => {
            if( (left == curNums )&& (right == curNums) ){
                result.push(curStr);
                return;
            }
            
            if( left < curNums){
                produce(curStr+'(',left +1 ,right,curNums);
            }
            if( right < left){
                produce(curStr+')',left,right+1,curNums);
            }
        };
        
    produce('',0,0,n);
    
    return result;
};

这个算法其实更暴力,妙在使用递归和保持左右括号平衡的方法将一个看似复杂的问题简化了,我们走一遍流程哈,假如 n = 3对,刚开始 肯定是左半边括号加,

然后进入递归

此时left为1,继续

此时left为2,继续

此时left为3了,右半括号开始加,

此时right为1,继续

此时right为2,继续递归

此时right为3,

result里边push进((()))

最后一层函数返回

倒数第二层返回,直到返回到left为2时的状态

进入到 第三个if里边,这时候 curStr = ((),继续递归

......

直到结束。

我是真的觉得这个算法很妙,确实很钦佩第一个想出此种算法的人,妙极!因为递归,所以函数上下文可以保留函数的环境,也就是保存了‘(’和‘)’的各种排列,并且是平衡的,只要平衡(即左右括号数列相等)就是有效的。

高手高手!

本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
0条评论
作者最新博文
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学