这是我参与更文挑战的第18天,活动详情查看: 更文挑战
有效的括号(题号20)
题目
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
示例 4:
输入:s = "([)]"
输出:false
示例 5:
输入:s = "{[]}"
输出:true
提示:
1 <= s.length <= 104
s
仅由括号'()[]{}'
组成
链接
解释
这题啊,这题是经典垃圾小题目。
一开始笔者想多了,以为不一定非得按照顺序来,于是进行了一波操作,结果这题压根就不支持这样的格式,比方说([)]
,这也可以构成两个完整的括号,只是顺序上不一样。
结果这题压根没有这么复杂,这种情况不需要考虑,直接GG,题目认为对的情况是这样的:([{}]{})
,不存在包裹一半的情况发生。
那这样做就简单了,直接一个栈就搞定了,搞一个对象,确定括号们的匹配关系:
obj = {
')': '(',
']': '[',
'}': '{'
}
之后如果是左括号统一推入到栈中,如果遇到右括号,和栈中的最后一个元素匹配,如果不是一对,返回false
,如果是一对,就去掉栈中的最后一个元素。
很简单的操作,这也是笔者第一时间想到的答案,其实这类匹配括号的题目基本上都可以用栈来操作,方便快捷。
自己的答案(栈)
var isValid = function(s) {
var stack = []
obj = {
')': '(',
']': '[',
'}': '{'
}
for (const symbol of s) {
if (!obj[symbol]) {
stack.push(symbol)
} else {
if (obj[symbol] !== stack.pop()) return false
}
}
return stack.length === 0
};
代码也就像解释中说的那样,用栈来进行括号的匹配。
需要注意的是最后一行代码,这里为什么不直接返回true
呢?其实是因为即使前面完成了所有的匹配,最后的结果也还是会剩几个单独的括号,这样的用例是不行的。
更好的答案(栈 + 剪枝)
上面这种解法其实是可以进行剪枝操作的,如果字符串的长度为奇数,显然在这题中是不能通过的,所以可以在开头直接进行判断,如果是奇数,直接返回false
。
这样还避免了无意义的运算,官方答案就有这样的判断👇:
var isValid = function(s) {
if (s.length % 2 === 1) return false
var stack = []
obj = {
')': '(',
']': '[',
'}': '{'
}
for (const symbol of s) {
if (!obj[symbol]) {
stack.push(symbol)
} else {
if (obj[symbol] !== stack.pop()) return false
}
}
return stack.length === 0
};
更好的答案(正则 + 递归)
严格意义上来说,该方法不是更好的答案,因为不管是运行时间还是内存占用上都比不过前两种方法,不过笔者觉得很有意思,还是放在这里了。
先看看代码👇:
var isValid = function(s) {
while (s.includes('()') || s.includes('[]') || s.includes('{}')) {
if (s.includes('()')) {
s = s.replace('()', '')
}
if (s.includes('[]')) {
s = s.replace('[]', '')
}
if (s.includes('{}')) {
s = s.replace('{}', '')
}
}
return s.length === 0
};
这方法看起来是不是有点暴力,但又感觉有点意思。
逻辑很简单,如果遇到匹配的括号,就直接替换掉,就这样一直迭代,迭代到字符串中没有成对的括号为止,最后返回字符串的长度,如果长度长度为0,则证明是符合条件的字符串,如果不为0,证明该字符串有问题,返回false
。
或者可以直接去掉迭代里面的判断,替换就完事了,哪管那么多,再加上一点剪枝👇:
var isValid = function(s) {
if (s.length % 2 === 1) return false
while (s.includes('()') || s.includes('[]') || s.includes('{}')) {
s = s.replace('()', '')
s = s.replace('[]', '')
s = s.replace('{}', '')
}
return s.length === 0
};
运行时间有了些许提升,从原来的5%上升到了15%,但内存占用毫无变化,依旧是5%。
这种答案仅仅是提供思路,真正用这种办法可能会被喷个半死。
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇
有兴趣的也可以看看我的个人主页👇