题目描述
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解决方法
字符串法
思路:应用replace函数,对字符串进行多次遍历,每次都将最小的那个匹配括号替换掉,最后看字符串有无剩余字符即可。
代码实现:
class Solution {
public:
bool isValid(string s) {
int length = s.length();
int temp = length / 2;
//括号成对出现,遍历次数为字符串长度一半即可全部替换
while(temp>0)
{
/*
经查阅资料知,find函数没找到会返回一个特别的标记npos,是一个int型的
没有if的话 会导致replace函数越界,
*/
if(s.find("()")<length)
s = s.replace(s.find("()"), 2, "");
if(s.find("[]")<length)
s = s.replace(s.find("[]"), 2, "");
if(s.find("{}")<length)
s = s.replace(s.find("{}"), 2, "");
temp--;
}
return (s.length() ==0) ? true:false;
}
};
find函数的掌握不深,开始报错分析了很多遍没找出来问题所在。
find函数用法详解
replace函数用法详解
但这个解法不太理想,若不能匹配的括号字符串很长,但程序判断不了它不匹配,程序还是执行了temp次,一比较才知道不匹配。
这个解法虽然思路简单,但执行耗时过长,待优化。
辅助栈法
思路:应该是比较理想的一种解法了。情况就那么几种,新入字符要么开括号,要么闭括号,闭括号就让它和栈顶元素比较,匹配就弹出栈顶元素,不匹配的话直接break;若闭括号遇到空栈也直接break。
简化来说:循环成立的情况:新入开括号;闭括号匹配成功;循环break:else
为方便理解,我把闭括号遇到空栈也直接break的情况单独写了,也可以不写。
class Solution {
public:
bool isValid(string s) {
//哈希表,存储,以及栈
unordered_map<char, int> map{
{'(', 1},
{'[', 2},
{'{', 3},
{')', 4},
{']', 5},
{'}', 6}};
stack <char> st;
//用来判断如果第一个字符就是闭括号怎么办,以及其他不匹配的情况
bool unknown_true =true;
//遍历string s
//栈空/非空*新入的开还是匹配的闭或者不匹配的闭
for(char c:s)
{
//如果为开括号,将其入栈
if(1<=map[c]&&map[c]<=3)
st.push(c);
//栈空但新进字符为闭括号,break
else if(st.empty()&&4<=map[c]&&map[c]<=6)
{
unknown_true = false;
break;
}
//如果栈非空,且栈顶元素与接下来的字符(闭括号)相对应,出栈
else if(!st.empty() && map[st.top()]==map[c]-3 )
st.pop();
//栈非空但新入的字符不匹配
else
{
unknown_true = false;
break;
}
}
//如果for遍历完后,栈空,有两种情况
//要么遍历完括号全部弹出,括号匹配,unknown_true的值未被改变
//要么第一个就是闭括号没有进栈直接break,所以提前记录一下这种情况
//错误解答:直接return unknown_true,未考虑只输入了一个括号的情况
if(!st.empty())
unknown_true = false;
return unknown_true;
}
};
提交发现了错误:未考虑只输入了一个括号的情况,最后还是要加上if(!st.empty())语句来判断!!!
总的来说,当然还是这种好,replace有点傻瓜,这个带判断就没有做无用功,执行时间大幅度提升。