「前端刷题」20. 有效的括号

430 阅读2分钟

这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战

题目

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

 

示例 1:

输入: s = "()"

输出: true

示例 2:

输入: s = "()[]{}"

输出: true

示例 3:

输入: s = "(]"

输出: false

示例 4:

输入: s = "([)]"

输出: false

示例 5:

输入: s = "{[]}"

输出: true

 

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

解题思路

根据题意,我们可以推断出以下要点:

  1. 有效括号字符串的长度,一定是偶数!
  2. 右括号前面,必须是相对应的左括号,才能抵消!
  3. 右括号前面,不是对应的左括号,那么该字符串,一定不是有效的括号!

图解演示

代码

// 解法一
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 };

-w458

解三:

换一种思路,可以边遍历边匹配。也就是遍历的时候遇到左括号存入数组,下次遇到的第一个右括号必须和数组中最后一个元素匹配,否则为无效字符串,匹配完成后从数组中删除此元素。若最终数组为空,表示括号已全部匹配完,字符串有效。

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 //防止全部为左括号 };

-w458

最后

曾梦想仗剑走天涯

看一看世界的繁华

年少的心总有些轻狂

终究不过是个普通人

无怨无悔我走我路

「前端刷题」No.20