题目
20.有效的括号
题目描述
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/valid-parentheses
我的思路
如果这不是一道代码题目,而是单纯用人的直觉来做,
其实步骤是一眼望去从内层开始找成对的括号并消除,类似于我们小时候常玩的连连看游戏。
连连看的胜利是否则依靠最后图纸上是否还有残留未消除的方块来判断。
那么转化为代码,我们也可以遍历字符串,遇到成对的括号并消除(replace替换为空),如果把所有成对的括号都消除之后,字符串长度不等于0,即为字符串中有括号落单。
代码
public static boolean isValid(String s) {
int length = s.length() / 2;
for (int i = 0; i < length; i++) {
s = s.replace("()", "");
s = s.replace("{}", "");
s = s.replace("[]", "");
}
return s.length() == 0;
}
易错点
- 不循环遍历replace,而是直接对于字符串s进行replace。
则会导致如果字符串中的成对括号并不是连在一起的,那么只会替换一遍,答案出错。 - 由于我们遍历一次,如果成功找到,则会替换两个位置的符号,所以可以只查找字符串长度的一半。
- 最后判断时也可以把s和空比较,但是一定要用s.equals(“”);
不能简单使用s==“”;因为==比较的是堆内存中的地址,我们需要比较的是字符串的内容。
优化
依我的思路,虽然方法可行,但是时间效率非常低、内存消耗非常高。我看了讨论区中,有人提出用栈去解决这个问题,那我们来换一种方法吧。
我的思路
栈的特点是后进先出,那么谁进谁出呢?
遇到左括号,相对应的右括号进。遇到右括号,右括号出。
怎么出呢?
遇到右括号时,右括号和栈顶元素比较,有以下几种情况
- 相等 则移除
- 不相等 代表有不一样的括号字符 夹在 应该取出的括号中间 return false
- 栈顶为空,即栈为空。说明当前括号字符是多余的,没有相匹配的括号与之组成有效括号 return false
特殊情况:要判断的字符串中只有单个左括号
进行遍历后,对应右括号入栈,此时栈不为空。
只需要在原本应该return true的地方再判断一次栈是否为空。
用到了以下栈的方法
- stack.push(Object);把该元素推入栈顶
- stack.pop();查看栈顶元素并移除(如果只查看不移除可以使用stack.peek( ))
- stack.empty();查看栈是否为空
代码
public static boolean isValid(String s) {
//建立一个空栈
Stack<Character>stack = new Stack<Character>();
//把字符串转换为char数组来遍历循环
for(char c: s.toCharArray()){
//如果当前字符是左括号,那么把对应的右括号放进栈
if(c=='(')stack.push(')');
else if(c=='[')stack.push(']');
else if(c=='{')stack.push('}');
//如果当前字符是右括号,那么把当前字符和栈顶的元素进行比较
//情况1.if 相等,那么把当前字符推出栈,代表一对有效括号成功抛出
// if 不相等,就说明有不一样的括号字符 夹在 应该取出的括号中间,那么返回false
//情况2.如果栈是空的,说明当前括号字符是多余的,没有相匹配的括号与之组成有效括号,那么也返回false
else if(c!=stack.pop()||stack.empty())return false;
}
//以上循环中还缺少排除字符串只有单个左括号的情况
//如果单个左括号进行遍历后,对应右括号入栈,此时栈不为空。
return stack.empty();
}