`
jgsj
  • 浏览: 957371 次
文章分类
社区版块
存档分类
最新评论

LeetCode Generate Parentheses 深度分析理解

 
阅读更多

Generate Parentheses

Givennpairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, givenn= 3, a solution set is:

"((()))", "(()())", "(())()", "()(())", "()()()"

原创地址:http://blog.csdn.net/kenden23/article/details/16951299

此题给人一看就是眼花缭乱的感觉。在纷繁的特征中总结出来规律还真是非常难的。

网上分析实在太少了,令人难以看明白。

所以我在这里分析一下,觉得我分析得不好,或者深度不够的,请多多指教。

以我的思维,我是使用二叉树的思维思考这个算法的,不过最后没能自己成功的写出程序。查了查LeetCode论坛,使用的是递归算法,感觉真是精妙绝伦!因为我考虑这个递归树的时候有两个难点:

1 如何两边同时遍历一棵树?

2 如何剔除不适合的路径?比如最中间的路径是不满足条件的。

到底是什么样的树?构造出这样的概念树,我觉得就好理解很多了。

看看下面我画的树:

顺着路径对称地,比如最左边和最右边,遍历两个路径,就是一个解,除了最中间的不符合要求。所以要遍历这样的概念树,很困难。

下面是程序出处:http://discuss.leetcode.com/questions/203/generate-parentheses

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

void generator(vector<string> & ans, string s, int l, int r, int n) { // r/l: appearance of ) (
    if (l == n) {
        ans.push_back(s.append(n-r, ')'));
        return;
    }
    generator(ans, s+'(', l+1, r, n);
    if (l>r) generator(ans, s+")", l, r+1, n);
}

逐句看看吧,反正没多少。

if (l == n) {
        ans.push_back(s.append(n-r, ')'));
        return;
    }


这个功能是已经遍历了左边的树,然后这里并不需要遍历右边的树,而是非常巧妙地直接补上右括号“)”就完事了。没做过的话,真是想破头脑都难想出来。

而这样居然神奇地完成一个解了。

generator(ans, s+'(', l+1, r, n);


这句就是遍历左递归树,是先序遍历哦,有人说理解为后序,不对,应该是先序。因为s+'('就是先把"("加进去了,然后到下一层树节点。

左子树递归遍历完了就开始右子树递归遍历:

if (l>r) generator(ans, s+")", l, r+1, n);


右子树都是“)”右括号的,所以s+")"代表遍历右子树。

不过令人头痛的就是怎么理解if(l>r)这个条件?

看了些博客说理解为不能让右括号多于左括号,有一定道理,那为什么前面遍历左子树的时候,就是填写左括号“(”的时候,不添加一个判断左子树不能大于右子树的条件呢?所以这样理解好像不大合理。

我的理解,这句正是剔除中间不符合条件的路径的巧妙句子。

因为只有左子树的最右边的子树才会可能出现右括号")"大于左括号"("的情况的,所以这个条件真是"黄娟! 幼妇! 外孙"!


2014-1-25 update
递归回溯法的程序,其实题目并不难,上面的分析我重新看看,使用树的思维分析也可以,不过如果熟悉了,那么还是不需要分析的太麻烦,不过这样分析对思维锻炼很有好处。

本题最难的就是一个条件判断啦,如我重新写了个程序,如下。这个条件就是if (left < right),这是个十分难想出来的条件,最后怎么吃透这个条件呢?

我就是使用实例,反复走几遍,然后就确立了这个条件,这就是根据实例观察其中的规律的能力了。

虽然就是那么一个条件,自己摸索出来,难度还是相当大的。所以本题我觉得因人而异才能确定其难度指数,我觉得相对难度应该达到4.5星级了,不注意的话,面试的时候是很难写出正确的程序的。也许写个差不多的程序是可以的,不过所谓的差不多程序,就是差一点点没正确的程序,说到底就是错误的程序。

class Solution {
public:
    vector<string> generateParenthesis(int n) 
	{
		vector<string> rs;
		string s;
		genParenthesis(rs, s, n, n);
		return rs;
	}
	void genParenthesis(vector<string> &rs, string &s, int left, int right)
	{
		if (left==0)
		{
			rs.push_back(s);
			rs.back().append(right, ')');
			return;
		}

		s.push_back('(');
		genParenthesis(rs, s, left-1, right);
		s.pop_back();
		if (left < right)
		{
			s.push_back(')');
			genParenthesis(rs, s, left, right-1);
			s.pop_back();
		}
	}
};

难度指数: 4.5星级


分享到:
评论

相关推荐

    程序员面试宝典LeetCode刷题手册

    第四章 Leetcode 题解 1. Two Sum 2. Add Two Numbers 3. Longest Substring Without ...22. Generate Parentheses 23. Merge k Sorted Lists 24. Swap Nodes in Pairs 25. Reverse Nodes in k-Group 26. Remove Dupli

    leetcode信封-LeetCode:LeetCode解题

    leetcode信封 LeetCode LeetCode解题 源码目录 //main下为源码,test下为单元测试 │ src │ ├─main │ └─java │ └─com │ └─algorithm │ GeneratorParenthesis.java //22. Generate Parentheses | ...

    lrucacheleetcode-leetcode:leetcode

    lru缓存leetcode leetcode 1. Two Sum 2. Add Two Numbers 3. Longest Substring Without Repeating Characters 4. Median of Two Sorted Arrays 5. Longest Palindromic Substring 7. Reverse Integer 9. ...

    leetcode530-algorithm:算法

    leetcode 530 ** LeetCode 题目更新 ** 用来记录业余时间所做的算法题目,保持对于数据结构的熟悉。 ** Leetcode 题目列表 005 Longest Palindromic Substring 006 ZigZag Conversion 007 Reverse Integer 008 ...

    leetcode答案-LeetCode:不要放弃

    leetcode 答案LeetCode 算法的复杂度分析。...因为是递回求解,所以很抽象不好懂,这里以leetcode的generate-parentheses一道题目为例,给定n,要找出n个括号的各种组合,例如n=2 ,答案会是[(()), ()()]

    leetcode中国-LeetCodeAnswerCollections:LeetCode题解精选代码收集

    generate-parentheses【】【中等】 这是一道递归题目,想法很重要,保证括号合法性是另一个要点 private List result; public List generateParenthesis(int n) { result = new ArrayList(); _generate(0, 0, n, "")...

    leetcode2-Algorithms-Practice:创建此repo是为了跟踪我在解决问题方面的进展

    leetcode 2 LeetCode-练习 我的 Leetcode“解决方案”(在解决方案/文件夹中)来解决 leetcode 问题。 它用于练习和跟踪进度不是 100% 优化的。 我的账户链接 问题名称 运行时和内存使用 1. Two Sum 运行时间:4412 ...

    LeetCode 括号生成

    题目来源:https://leetcode-cn.com/problems/generate-parentheses/submissions/ 题目 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。 例如,给出 n = 3,生成结果为...

    leetcode添加元素使和等于-programmer_practices:算法实践

    leetcode添加元素使和等于 programmer_practices algorithm practices 最优解Book: 双栈实现getMin Stack. 双栈实现Queue. 递归和栈实现逆序操作一个栈. 仅用一个栈排序另一个栈. 打印两个有序链表的公共部分. 删除...

    Coding Interview In Java

    237 Generate Parentheses 575 238 Combination Sum 577 239 Combination Sum II 579 240 Combination Sum III 581 241 Combinations 583 242 Letter Combinations of a Phone Number 587 243 Restore IP Addresses ...

    Dir-For-LeetCode

    022_Generate_Parentheses 023_Merge_k_Sorted_Lists 024_Swap_Nodes_in_Pairs 025_Reverse_Nodes_in_k-Group 026_Remove_Duplicates_from_Sorted_Array 027_Remove_Element 028_Implement_strStr() 029_...

    cpp-算法精粹

    Generate Parentheses Sudoku Solver Word Search 总结 分治法 Pow(x,n) Sqrt(x) 贪心法 Jump Game Jump Game II Best Time to Buy and Sell Stock Best Time to Buy and Sell Stock II Longest Substring Without ...

Global site tag (gtag.js) - Google Analytics