[路飞]leetcode-20.有效的括号及相关栈的思想

258 阅读3分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」。

题目简述

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

有效字符串需满足:

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

先来一道简单的

假设只给你一个包括'('')'的字符串,判断字符串是否有效,你要怎么处理。(不用栈呢?)

思路分析

我们可以得到下述分析

  • 在任意一位置上,左括号 〉= 右括号
  • 在最后位置上,左括号 === 右括号
  • 在程序中只记录左数和右数即可

代码实现

var isVaild = function(s) {
    let lnum = 0, rnum = 0;
    const len = s.length;
    for(let i = 0; i < len; i++) {
        switch(s[i]) {
            case "(":
                ++lnum;
                break;
            case ")":
                ++rnum;
                break;
            default:
                return false;
        }
        if (lnume >= rnume) continue;
        return false;
    }
    return lnum === rnum;
}

继续深入

所以一定要用两个变量来存储数量么?还能不能继续处理

思路分析

  • l - r >= 0 差值任意位置均应该大于等于0
  • 记录一个变量 左边 + 1,右边 -1
var isVaild = function(s) {
    let lnum = 0;
    const len = s.length;
    for(let i = 0; i < len; i++) {
        switch(s[i]) {
            case "(":
                ++lnum;
                break;
            case ")":
                --lnum;
                break;
            default:
                return false;
        }
        if (lnume >= 0) continue;
        return false;
    }
    return lnum === 0;
}

思考

我们获得了怎样的思考方式?

  • 1、+1可以为“进”, -1可以为“出”
  • 2、一对括号可以等价为一个完整的事件
  • 3、(())可以看作事件与事件之间的完全包含关系
  • 4、由括号的等价变换可以得到一个全新的数据结构

我们可以得出栈的一句话介绍:栈,可以用来处理具有“完全包含”关系的问题

横向思考,我们常见的完全包含关系还有,函数递归、二叉树

函数递归的调用一般是完全包含关系(函数调用关系)

二叉树可以分开分析,树形节点代表集合,子节点代表子集

           1
         /   \
        2     3
     --------------
        (()())
   即 122331   

即 概念泛化

思路描述

回归主题,接下来继续来解决这道题

使用栈的思维来解决这道题

想要了解一下栈???点击这里直达

  1. 先分析边界值,要求括号两两匹配,因此边界值为,传入字符串且字符串长度为单数时一定无效
  2. 遇见左括号压栈,遇见右括号则将上一个压栈出栈对比,如果是对应的左括号,则匹配成功,继续进行下一个操作
  3. 最终对比完成后,栈中没有值则有效,栈中有值则无效
  4. 对比中如果出现无法比对,压栈与出栈匹配失败,此字符串则无效(题目要求有效字符串必须满足正确顺序)

代码实现

var isValid = function (s) {
  const map = new Map([
    ["(", ")"],
    ["[", "]"],
    ["{", "}"]
  ]);
  const arr = s.split("");
  const len = arr.length;
  const stack = [];
  if (len <= 1) return false;
  for (let i = 0; i < len; i++) {
    if (map.has(arr[i])) {
      stack.unshift(arr[i]);
    } else {
      const left = stack[0];
      if (map.get(left) === arr[i]) {
        stack.shift();
      } else {
        return false;
      }
    }
    if (i === len - 1 && stack.length === 0) return true;
    if (i === len - 1 && stack.length != 0) return false;
  }
};