Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
一、题目描述:
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。
示例
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
示例 4:
输入:s = "([)]"
输出:false
示例 5:
输入:s = "{[]}"
输出:true
提示:
1 <= s.length <= 104s仅由括号'()[]{}'组成
二、题解:
方法一 暴力替换法
-
方案。此题无非就是替换成对存在的三种括号,而且输入为字符串,所以想到了replace和replaceAll两种替换方案。
tips: 最后实践出来两种方案效率几乎一致,replaceAll循环次数更少,但是单次循环耗时间更长,replace循环次数多,但是单次循环时间短
-
思路。但由于不知道哪种括号在前,所以每次需要试着替换3种,不匹配也不会改变字符串。
tips: replace不会改变原字符串,所以需要赋值改变字符串本身
核心语句:
s = s.replace('{}','').replace('[]','').replace('()','')
- 循环。因为是替换的思路,所以循环也不知道具体次数,只知道大概小于等于字符串长度的一半,推荐使用while
- 跳出循环。因为是替换的思路,所以可以根据替换前和替换后的长度是否一致决定可以跳出循环
- 返回结果。根据跳出循环时字符串长度决定的,如果有长度,则返回false,否则返回true。
代码:
var isValid = function(s) {
while(true){
let _len = s.length
s = s.replace('{}','').replace('[]','').replace('()','')
let len = s.length
if(_len === len){
break
}
}
if(s.length){
return false
}
return true
};
优化
优化有几个思路。
- 更快出结果
- 少产生变量
- 提升计算效率
优化后代码
var isValid = function(s) {
// 空字符串符合条件
if (!s) {
return true
}
if (s.length % 2 !== 0) {
return false
}
while(true){
if(!s.length){
return true
}
let _len = s.length
s = s.replaceAll('{}','').replaceAll('[]','').replaceAll('()','')
let len = s.length
if(_len === len){
return len === 0
}
}
};
方法二 栈
- 方案。本质上该题使用的是匹配对称问题,其实和堆栈一致,入栈元素和栈内元素是否匹配,匹配则出栈,否则则入栈
- 思路。因为该题是匹配对应的括号而不是一致性,所以需要创建一个键值对对象或者二位数组的方式实现匹配
核心语句:
const map = {
'{':'}',
'[':']',
'(':')'
}
if(map[stack.pop()] !== item) return false
- 原理。stack.pop() 是栈出栈的方案,如果该栈顶元素和遍历元素匹配,匹配一致则已经自动出栈,否则则不用循环了,因为已经不匹配
- 循环。因为需要遍历每一个元素,对字符串的遍历,我选择了for...of循环
- 结果。根据跳出循环时栈的长度决定的,如果有长度,则返回false,否则返回true。
结合方案一优化后的代码:
var isValid = function(s) {
if (!s) {
return true
}
if(s.length%2 !== 0){
return false
}
let map = {
'{':'}',
'[':']',
'(':')'
}
let stack = []
for(let item of s){
if(map[item]){
stack.push(item)
} else {
if( !stack.length || map[stack.pop()] !== item){
return false
}
}
}
return stack.length === 0
};
🤣基本也是战胜了暴力方案一
三、总结
- 此题可以使用替换法和栈解法两种方案,根据方案不同选择不同循环和判断是否可以跳出循环来解题。
- 替换法使用replace或replaceAll替换成对存在的三种括号,加上while循环,判断字符串是否已经不改变了跳出循环
- 栈解法使用栈思路,判断入栈元素和栈内元素是否匹配,匹配则出栈,否则则入栈,加上for...of循环,使用stack.pop() 取出栈顶元素,去和遍历元素匹配,匹配一致则已经自动出栈,否则则不用循环了,因为已经不匹配
文中如有错误,欢迎在评论区指正