- 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
目录
- 有效的括号 (
if..else实现) - 有效的括号 (
switch..case实现) - 有效的括号 (
对象分支实现) - 有效括号的
多个场景 括号匹配--栈解决
一 有效的括号 (if..else 实现)
思路: 遍历字符串时,如果遇到左括号,就把对应的右括号保存到数组当中.
/**
* @param {string} 字符串
* @return {boolean} 布尔值
*/
var isValid1 = function (str) {
// 如果 item 是 ( 就在stack中存入 [')'], 如果 item 是 [ 就在stack中存入 [']']
const stack = []; // 数组中每一次遍历后,最多只有一个元素, 不论,是否是有效括号,数组都会被清空
for (let i = 0; i < str.length; i++) {
let item = str[i];
if(item === '(') {
stack.push(')');
} else if(item === '[') {
stack.push(']');
} else if(item === '{') {
stack.push('}');
} else {
// 这里的 stack 1, "[]" 时,是在数组中存了当前遍历的前半括号,对应的后半括号
// 2, "[}"时, stack 存的是 [']'], 但是 当前的item为 } 所以不是有效括号.
console.log('stack:',stack,'item:',item);
if (item !== stack.pop()) { // 一个或多个时: "[}"时,或者 "[]()[}"时, 在判断时,已经把数组中的唯一元素pop出去,并且数组清空了.
return false;
}else{ // "[]" 时 或者 "[](){}[]()"时
// return true // 这里不能return true, 否则只能判断一对括号是不是有效括号
}
console.log('stack---:',stack);
}
}
console.log('stack---:',stack);
// 非有效括号在遍历中就return出去了
// 如果都是有效括号,遍历完成后, 走到这里就肯定是 有效括号, 但是,除了多个左括号的种种情况 "[[" '((' "{{" "[[[.."
// return true; // 除了上面 "[[" '((' "{{" "[[[.." 类似的情况有问题,其他情况都可以 return true;
return stack.length === 0;
};
// 第一次遍历把左括号,对应的右括号保存到数组中.
// 第二次遍历,拿第二次遍历的item与数组当中的元素比较,并且利用pop的特性把数组中唯一的元素清空了,如果相等就是有效括号,如果不相等就是 非有效括号
var str = "[[[[";
isValid1(str);
// stack---: (4) [']', ']', ']', ']']
false
二 有效的括号 (switch..case 实现)
写这个其实没啥意义, 分支语句的另外一种写法 这里可以用函数式的方式来写
R.cond()
也是一样的.
var isValid = function (str) {
const stack = [];
for (let i = 0; i < str.length; i++) {
let item = str[i];
switch (item) {
case '(':
stack.push(')');
break;
case '[':
stack.push(']');
break;
case '{':
stack.push('}');
break;
default:
if (item !== stack.pop()) {
return false;
}
}
}
return stack.length === 0;
};
var str = '[]()';
var str1 = '[[['
var str2 = '][]()'
isValid(str); // true
isValid(str1) // false
isValid(str2) // false
三 对象分支 实现
var isValid = function(str) {
const stack = [],
map = {
"(":")",
"{":"}",
"[":"]"
};
for(const item of str) {
if(item in map) {
stack.push(item);
continue;
};
if(map[stack.pop()] !== item) return false;
}
return !stack.length;
};
var str = '[]()';
var str1 = '[[['
var str2 = '][]()'
isValid(str)
四 有效括号的多个场景
1) 多个左括号时, ']' , ']]' , ')))' , '}}}}'
var str = "[[[[";
isValid1(str);
// 此时 stack为: [']', ']', ']', ']'];
遍历时,不断的push到数组当中,对应的右括号,比如,有4个左括号,就push4次 右括号到数组当中, 遍历完成后, 直接走到最后一步, 此时
数组中存了4个右括号,return stack.length === 0为False
步骤
var str = "[[[[";
- 第一次遍历, push 到 stack 中为
[']'] - 第二次遍历, 继续 push 到 stack 中为
[']',']'] - 第三次遍历, 继续 push 到 stack 中为
[']',']',']'] - 第四次遍历, 继续 push 到 stack 中为
[']',']',']',']'] - 此时
stack为[']',']',']',']'] - 执行
return stack.length === 0; - 返回
false
2) 一或多个非有效括号 '[}'时, 或者 "[}"时
str = '[}';
// 关键走这里
if (item !== stack.pop()) {
return false;
}
一个或多个时: "[}"时,或者 "[}()[}"时, 在判断时,已经把数组中的唯一元素pop出去,并且数组清空了.
直到遇到的下一下偶数索引的括号不是对应的右括号时,就直接return false出去这个函数,结束循环跳出函数.
比如当str = '[}' 时 ,在第一次遍历时, item为 [ 时 数组stack中存入 [']'],然后,在第二次遍历时,比较的当前item为 } 号, stack.pop出的元素为 ] 号,所以就直接返回 false
步骤
- 第一次遍历, push 到 stack 中为 [']']
- 第二次遍历, 比较 item 此时为 '}' 与 stack.pop的返回值 ']' 不相等. stack.pop()时,并且把数组清空了.
- return false 跳出函数,返回false
3) 一个或多个有效括号时, "[]" 时 或者 "{}"时
var str = "[](){}[]()";
isValid1(str);
步骤
var str = "[](){}[]()";
- 第一次遍历, push 到 stack 中为 [']']
- 第二次遍历, 在比较item与stack中的元素时, stack.pop(),并且把数组清空了.
- 第三次遍历, push 到 stack 中为 [')']
- 第四次遍历, 在比较item与stack中的元素时, stack.pop(),并且把数组清空了.
- 直到 "{}" 所有的都遍历完成.
- 此时的stack为空数组 []
- 执行 return stack.length === 0;
- 返回 true
4) 一个或多个有效括号时, "[]" 时 或者 "[{([])}]"时
利用
棧 的特性, push 和 pop来处理这种场景
var str = "[{([])}]";
isValid1(str);
五 括号匹配 -- 栈解决
括号匹配是使用栈解决的经典问题。
题意其实就像我们在写代码的过程中,要求括号的顺序是一样的,有左括号,相应的位置必须要有右括号。如果还记得编译原理的话,编译器在
词法分析的过程中处理括号、花括号等这个符号的逻辑,也是使用了栈这种数据结构。
1) 有效括号-场景回顾
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。
分析完之后,代码其实就比较好写了,
但还有一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!
参考
总结
有效括号: 遍历是必须的,在遍历到奇数item时,我们就可以知道偶数item是啥了, 然后,进行比较即可.- 遍历字符串的方式:
for与for...of 括号匹配是使用栈解决的经典问题。