LeetCode 20_Valid Parentheses
2015-09-26 19:59
411 查看
这么多天了,才刷到20题,真是伤心啊,不过毕竟坚持了下来了,也算对得起自己了,这道题的难度也是简单,不过倒是挺有意思的,实现的方式也比较多,用来学习算法还是不错的。
Given a string containing just the characters
determine if the input string is valid.
The brackets must close in the correct order,
all valid but
not.
题目用一句话来说就是括号匹配,给定一个由圆括号、大括号、方括号组成的字符串,判断其是否可以配对成功,其实有过编程经验的人都知道括号匹配的问题,写代码的时候也要注意这些东西,如果写的不匹配了一般的编译器都会提示错误的,那编译器是怎么判断括号是否配对成功的呢,今天就来让你实现以下匹配的算法。
括号的匹配规则用一句话说就是和最近的一个可以匹配的匹配,可以嵌套但不能重叠。也就是说“([]{})”是可以的,但”({)}“是不可以的。
该怎么考虑呢?这就看你有多少经验了,要是没有任何经验就凭自己想是有点儿困难的,不过我们也不要放弃,多动脑子是没有坏处的,这次我就把自己的探索经历给大家分享一下,希望各位也可以从中得到一些启发,更重要的是培养自主思考的能力。
首先,这是一个配对问题,要配对就肯定要找一对嘛,怎么找呢?给你一个”括号串“,你首先拿到了第一个”半括号“,这个半括号如果是右括号那肯定就直接输出false了,如果是左括号呢?你去哪儿找它的另一半儿呢?紧挨着从第二个往后找?因为可以嵌套,如果一连几个都是左括号,而且有同型的的话该怎么办呢?你遇到的第一个可以匹配的右括号是该跟第一个匹配还是跟后面的同型的匹配呢?应该跟最后一个同型的匹配。那他俩配完了他俩中间的呢?万一是一个半括号那就false,要不是还要做其他判断。。。好像有点儿复杂。那从字符串尾开始找呢?显然更不靠谱了,倒数第一个右括号应该跟它前面倒数第一个左括号匹配,跟第一个左括号很可能没有一毛钱的关系。。。显然这种拿到第一个找其”对象“的思路是不好使的。
虽然第一步探索失败了,但从中我们发现一个点,那就是第一个右括号是一定和它前面的同型左括号相匹配的。我们自然有了这样的想法,如果先找到第一个右括号然后找它的”对象“呢?也就是找到第一个右括号往前面找它的”对象“,这里的一个问题就是找的过程中怎么处理其他左括号,显然第一个右括号肯定要紧挨着其”对象“,否则一定会有半个括号或者重叠括号,可以直接输出false。那怎么处理嵌套情况呢?这里就要看大家有没有这样的经历了,最直接的想法就是把已经配对的括号”删去“。如果想到这一点,说明你离成功只差最后一步了,因为算法已经设计完成了:找到第一个右括号,判断其是否存在对象,不存在就返回false存在就删除这一对,然后找第二个右括号。。。
既然算法设计已经完成,那还差哪一步呢?找右括号显然不是问题,找对象也比较容易解决,找不到返回false也不用多说,,,,没错,就是删除这一对有点儿问题,按理说这已经是程序设计以及语言特性的问题了。不同的程序设计者有不同的策略,不同的语言也有不同的方法,你也可以设计一个可以删除元素的string类型,那问题就解决了。我们这里不做这种事情,而是讲两种比较通用的思想:测试表和栈。
测试表是我自己的实现思路,就是构建一个测试表,分别对应每一个半括号,如果括号已经配对成功,那么则将表中对应位设为true(对应上面提到的删除括号),在历遍括号string的过程中根据测试表判断是否可以跳过该括号(配完对的可以跳过)。到最后判断是否测试位全部为true,如果全为true证明所有括号都匹配成功,否则证明匹配失败。对应的代码如下:
第二种是从大神那儿学来的,就是利用栈这种数据结构来实现算法,经过分析发现栈这种东西就是为这种算法而生的,二者契合度为百分之九十。这个就不解释了,留给大家自己分析吧,把代码奉上,在这里感谢 TJUYZL大神的分享
正如前面所说,算法设计和程序设计在本题中是分开进行的,两种代码其实是用的一种算法,大家可以仔细考虑一下。吃饭的时间快到了,不多说了
Given a string containing just the characters
'(',
')',
'{',
'}',
'['and
']',
determine if the input string is valid.
The brackets must close in the correct order,
"()"and
"()[]{}"are
all valid but
"(]"and
"([)]"are
not.
题目用一句话来说就是括号匹配,给定一个由圆括号、大括号、方括号组成的字符串,判断其是否可以配对成功,其实有过编程经验的人都知道括号匹配的问题,写代码的时候也要注意这些东西,如果写的不匹配了一般的编译器都会提示错误的,那编译器是怎么判断括号是否配对成功的呢,今天就来让你实现以下匹配的算法。
括号的匹配规则用一句话说就是和最近的一个可以匹配的匹配,可以嵌套但不能重叠。也就是说“([]{})”是可以的,但”({)}“是不可以的。
该怎么考虑呢?这就看你有多少经验了,要是没有任何经验就凭自己想是有点儿困难的,不过我们也不要放弃,多动脑子是没有坏处的,这次我就把自己的探索经历给大家分享一下,希望各位也可以从中得到一些启发,更重要的是培养自主思考的能力。
首先,这是一个配对问题,要配对就肯定要找一对嘛,怎么找呢?给你一个”括号串“,你首先拿到了第一个”半括号“,这个半括号如果是右括号那肯定就直接输出false了,如果是左括号呢?你去哪儿找它的另一半儿呢?紧挨着从第二个往后找?因为可以嵌套,如果一连几个都是左括号,而且有同型的的话该怎么办呢?你遇到的第一个可以匹配的右括号是该跟第一个匹配还是跟后面的同型的匹配呢?应该跟最后一个同型的匹配。那他俩配完了他俩中间的呢?万一是一个半括号那就false,要不是还要做其他判断。。。好像有点儿复杂。那从字符串尾开始找呢?显然更不靠谱了,倒数第一个右括号应该跟它前面倒数第一个左括号匹配,跟第一个左括号很可能没有一毛钱的关系。。。显然这种拿到第一个找其”对象“的思路是不好使的。
虽然第一步探索失败了,但从中我们发现一个点,那就是第一个右括号是一定和它前面的同型左括号相匹配的。我们自然有了这样的想法,如果先找到第一个右括号然后找它的”对象“呢?也就是找到第一个右括号往前面找它的”对象“,这里的一个问题就是找的过程中怎么处理其他左括号,显然第一个右括号肯定要紧挨着其”对象“,否则一定会有半个括号或者重叠括号,可以直接输出false。那怎么处理嵌套情况呢?这里就要看大家有没有这样的经历了,最直接的想法就是把已经配对的括号”删去“。如果想到这一点,说明你离成功只差最后一步了,因为算法已经设计完成了:找到第一个右括号,判断其是否存在对象,不存在就返回false存在就删除这一对,然后找第二个右括号。。。
既然算法设计已经完成,那还差哪一步呢?找右括号显然不是问题,找对象也比较容易解决,找不到返回false也不用多说,,,,没错,就是删除这一对有点儿问题,按理说这已经是程序设计以及语言特性的问题了。不同的程序设计者有不同的策略,不同的语言也有不同的方法,你也可以设计一个可以删除元素的string类型,那问题就解决了。我们这里不做这种事情,而是讲两种比较通用的思想:测试表和栈。
测试表是我自己的实现思路,就是构建一个测试表,分别对应每一个半括号,如果括号已经配对成功,那么则将表中对应位设为true(对应上面提到的删除括号),在历遍括号string的过程中根据测试表判断是否可以跳过该括号(配完对的可以跳过)。到最后判断是否测试位全部为true,如果全为true证明所有括号都匹配成功,否则证明匹配失败。对应的代码如下:
class Solution { public: bool isValid(string s) { int len=s.size(); if(len==0) return true; if(s[0]==')'||s[0]=='}'||s[0]==']') return false; vector<bool> test(s.size(),false);//测试表,全部为0 int lef=0,rig=0; while(rig<len) { //跳过所有左括号 if(s[rig]=='('||s[rig]=='{'||s[rig]=='[') rig++; else { lef=rig-1;//指向右括号左边一个 while(test[lef]==true && lef>0)lef--;//跳过所有已经匹配过的括号 if(lef<0)return false; if(( s[lef]=='('&&s[rig]==')') || (s[lef]=='{'&&s[rig]=='}') || (s[lef]=='['&&s[rig]==']') ) { test[lef]=test[rig]=true;rig++; } else return false; } } for(int i=0;i<len;++i) if(test[i]==false)return false; return true; } };代码没什么可说的,注意边缘输入就可以了。
第二种是从大神那儿学来的,就是利用栈这种数据结构来实现算法,经过分析发现栈这种东西就是为这种算法而生的,二者契合度为百分之九十。这个就不解释了,留给大家自己分析吧,把代码奉上,在这里感谢 TJUYZL大神的分享
class Solution { public: bool isValid(string s) { int n = s.size(); if(n==0) return true; if(n%2==1) return false; stack<char> str; str.push(s.at(0)); int i=1; while(i<n){ if(s.at(i)=='(' ||s.at(i)=='['||s.at(i)=='{'){ str.push(s.at(i)); } else{ char tmp = str.top(); if(valid(tmp,s.at(i))){ str.pop(); } else{ return false; } } i++; } if(str.empty()) return true; else return false; } bool valid(char a, char b){ if((a=='(' && b==')') || (a=='[' && b==']') || (a=='{' && b=='}')) return true; else return false; } };以后碰到类似的题,希望大家可以想到栈这种数据结构,还是那句话,数据结构这门课是程序员的内功心法,是必须要学的,另外测试表的用处可能更灵活一点,试用的情况也比较多,大家最好也理解一下。
正如前面所说,算法设计和程序设计在本题中是分开进行的,两种代码其实是用的一种算法,大家可以仔细考虑一下。吃饭的时间快到了,不多说了
相关文章推荐
- 关于错误:将截断字符串或二进制数据
- (第二课1.1.4节)myvivi(2th)
- 信息安全系统设计基础第二周学习总结
- Java开发中23中设计模式
- 学java 的感受
- Android的网络开发Http协议详解之二
- java 添加一个线程、创建响应的用户界面 。 演示示例代码
- Visual Studio 2012 与此版本的 Windows 不兼容 解决
- hdu1753()模拟大型实景数字相加
- LeetCode(22)Generate Parentheses
- mysql dba 面试题部分答案(转)
- 模仿JavaAppArguments.java示例
- LeetCode(22)Generate Parentheses
- 浅谈 C++ 中的 new/delete 和 new[]/delete[]
- #SC2440虚拟地址到物理地址的转换
- (第三期1.1.4节)myvivi(1th)
- 对全概率与贝叶斯的理解
- faster rcnn
- WAMP Server多站点出现You don t have permission to access / on this server错误
- java学习笔记--类与接口