这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
题目
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
示例 1:
输入: s = "()"
输出: true
示例 2:
输入: s = "()[]{}"
输出: true
示例 3:
输入: s = "(]"
输出: false
示例 4:
输入: s = "([)]"
输出: false
示例 5:
输入: s = "{[]}"
输出: true
提示:
1 <= s.length <= 104s仅由括号'()[]{}'组成
解题思路
根据题意,我们可以推断出以下要点:
- 有效括号字符串的长度,一定是偶数!
- 右括号前面,必须是相对应的左括号,才能抵消!
- 右括号前面,不是对应的左括号,那么该字符串,一定不是有效的括号!
图解演示
代码
// 解法一
let isValid = function(s) {
let stack = [], length = s.length;
if(length % 2) return false;
for(let item of s){
switch(item){
case "{":
case "[":
case "(":
stack.push(item);
break;
case "}":
if(stack.pop() !== "{") return false;
break;
case "]":
if(stack.pop() !== "[") return false;
break;
case ")":
if(stack.pop() !== "(") return false;
break;
}
}
return !stack.length;
};
// 解法二
var isValid = function(s) {
s = s.split('');
let sl = s.length;
if (sl % 2) return false;
let map = new Map([[')', '('], [']', '['], ['}', '{']]);
let stack = [];
for(let i of s){
if (map.get(i)) {
if (stack[stack.length - 1] !== map.get(i)) return false;
else stack.pop();
} else {
stack.push(i);
}
}
return !stack.length;
};
其他思路
解一:
找到最内层的括号对,消去,重复此过程,若存在无法消去的字符则说明字符串无效。
var isValid = function (s) { while (s.length) { var temp = s; s = s.replace('()', ''); s = s.replace('[]', ''); s = s.replace('{}', ''); if (s == temp) return false } return true; };
解二:
解一跑出来的速度和内存都不尽人意,我怀疑是
replace的问题,就用同样的思想重写了一遍,没想到性能更差了。
var isValid = function (s) { var map = { "(": ")", "[": "]", "{": "}" } while (s.length) { var left = s[0]; if (!(left in map)) return false; var i = 1; while (s[i] != map[left] && i < s.length) left = s[i++]; if (s[i] != map[left]) return false s = s.slice(0, i - 1) + s.slice(i + 1, s.length); } return true };
解三:
换一种思路,可以边遍历边匹配。也就是遍历的时候遇到左括号存入数组,下次遇到的第一个右括号必须和数组中最后一个元素匹配,否则为无效字符串,匹配完成后从数组中删除此元素。若最终数组为空,表示括号已全部匹配完,字符串有效。
var isValid = function (s) { var map = { "(": ")", "[": "]", "{": "}" } var leftArr = [] for (var ch of s){ if (ch in map) leftArr.push(ch); //为左括号时,顺序保存 else { //为右括号时,与数组末位匹配 if(ch != map[leftArr.pop()]) return false; } } return !leftArr.length //防止全部为左括号 };
最后
曾梦想仗剑走天涯
看一看世界的繁华
年少的心总有些轻狂
终究不过是个普通人
无怨无悔我走我路
「前端刷题」No.20