有效的括号
| Category | Difficulty | Likes | Dislikes |
|---|---|---|---|
| algorithms | Easy (39.08%) | 953 | - |
Companies
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
/*
* @lc app=leetcode.cn id=20 lang=javascript
*
* [20] 有效的括号
*/
/**
* @param {string} s
* @return {boolean}
*/
var isValid = function(s) {
};
1
这种配对的问题,特别适合使用栈这种数据结构来解决.
首先,左括号我们是无法判断是否合法的
因为所谓的不合法是当右括号与左括号不匹配的时候才发生的
-
那么我们遇到左括号的时候,先把他压入栈中
-
当我们遇到右括号的时候,刚好就可以与栈中的左括号进行匹配,如果正确,就把左括坏出栈
-
如果最终栈为空,说明全部匹配成功
那代码实现起来的逻辑就很简单了
遍历s,如果是左括号就压栈,如果是右括号就与栈顶元素进行匹配,匹配成功执行出栈操作
如果遍历完成后,栈中无元素,说明是有效字符串
这里在判别左右字符串有个技巧,就是使用map
let map = new Map([
[')', '('],
[']', '['],
['}', '{']])
当然,直接使用对象也是可以的
let map = { ')': '(', ']': '[', '}': '{' }
使用map是为了更强的语义性
我们把可能是右扩号的值作为key
然后把可能是左扩号的值作为value
当我们在遍历时,判断一个元素是左括号还是右括号时,就可以在map里面查询
for (const c of s) {
if (!map.has(s)) {
// 如果不在字典里 说明 只能是 左括号 }])
}
else if() {
// 否则 就是 右括号 ([{
}
}
注意
map.has()是判断key元素的
-
如果是左括号
我们就进行压栈操作
if (!map.has(s)) stack.push(c) -
如果是右括号
我们就要与栈顶元素进行匹配,且栈中必须有元素,如果想要匹配栈中却没有元素直接返回
false取出栈顶元素
stack.pop()然后判断是不是该右括号对应的左括号map.get(c)else if (!stack.length || map.get(c) !== stack.pop()) return false!stack.length和stack.length !== 0是一样的,比较简洁而已因为
console.log(0 == false); //true数字0可以转换为false -
当遍历完后
如果栈中元素为0,说明该字符串合法
return !stack.length // return stack.length === 0 // 两种写法是一样的
综上,代码就为
var isValid = function (s) {
let stack = []
let map = new Map([
[')', '('],
['}', '{'],
[']', '[']
])
for (const c of s) {
if (!map.has(c))
stack.push(c)
else if (!stack.length || map.get(c) != stack.pop())
return false
}
return !stack.length
}
当然在map的初始化那么的真的很绕
[[key,value],[key,value],...]
我们可以使用对象的写法写一个
var isValid = function (s) {
let stack = []
let map = {
')': '(',
'}': '{',
']': '['
}
for (const c of s) {
if (!(c in map))
stack.push(c)
else if (!stack.length || map[c] != stack.pop())
return false
}
return !stack.length
}
存储就不用说了,判断元素是否存在使用in,取的话直接使用obj[key]
图
输入: "([)]"
输出: false