给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
显然这题是运用了栈的思维方式。
我们先将分成两类 A类(“(” “[” “{”)和B类(“)” “}” “]”)
首先我们可以知道,如果s的长度为奇数,直接返回false。
如果是偶数,如下分析
1.例如我们得到s中的第一个字符(A类)存入栈里。(如果是B类后面会有说明)
2.然后分析第二个字符,如果还是A类,继续存。如果是B类,就和最后存入栈里的元素进行比较。
1)两者对应,栈里的最后元素删去。长度-1
2)两者不对应(实际上已经能够说明false了),直接返回false。
如果第一个字符是B类,他和栈里的元素(空)比较,是不对应的。所以在分析任何一个元素 实际上判断条件都是2.。
这样一直进行到s中所有元素都被分析过为止。
看最终栈里还存不存在符号。存在,返回false。不存在。返回true。
代码如下
public class Solution {
public bool IsValid(string s) {
if(s.Length%2!=0) return false;
string[] queue = new string[s.Length];
int lenque = 0; //栈的长度
for (int i = 0; i < s.Length; i++)
{
string index=s.Substring(i,1);
if (index=="("||index=="["||index=="{")
{
queue[lenque]=index;
lenque++;
}
else if(lenque==0&&(index==")"||index=="]"||index=="}"))
{
return false;
}
else if(index==")"&&queue[lenque-1]=="(")
{
queue[lenque-1]=null;
lenque--;
}
else if(index=="]"&&queue[lenque-1]=="[")
{
queue[lenque-1]=null;
lenque--;
}
else if(index=="}"&&queue[lenque-1]=="{")
{
queue[lenque-1]=null;
lenque--;
}
else //两者不对应的情况,即2.2)中描述的情况
{
return false;
}
}
return lenque==0?true:false;
}
}
这里其实代码的实现得不太好,也是报错了好久才勉强实现上述的想法。
主要原因是如果字符串(假设这个字符串是 (())}] )前面有一部分是正确的,但是后面直接是B类,那么我在判断条件中的queue[lenque-1]的lenque-1为-1,会报错。所有必须加上第二个else if
else if(lenque==0&&(index==")"||index=="]"||index=="}"))
{
return false;
}
但结果还是不错的,实现速度不慢。
LeetCode测试用例不完善
最后,我发现leetcode这题的测试用例不够完善。
我有一份错误代码是上面的代码里删除了最后一个else,这个明显是不正确的。
我自己也用"((]]))"这个应该返回false的例子代入,结果返回了true。这说明这个代码的确没有实现题目的要求。
但是当时我提交后发现它76个测试用例都通过了……
本来我也不会发现自己的这份代码写错了,结果在写这篇博客分析的时候,感觉有问题,就回去自己测试了一下,结果被我自己发现了错误……
当然我在上面贴的代码是正确的,是在写的时候就已经改好了。