20有效的括号(JS)

2,343 阅读3分钟

有效的括号

Category Difficulty Likes Dislikes
algorithms Easy (39.08%) 953 -
Tags

string | stack

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

有效字符串需满足:

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

注意空字符串可被认为是有效字符串。

示例 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

这种配对的问题,特别适合使用栈这种数据结构来解决.

首先,左括号我们是无法判断是否合法的

因为所谓的不合法是当右括号与左括号不匹配的时候才发生的

  1. 那么我们遇到左括号的时候,先把他压入栈中

  2. 当我们遇到右括号的时候,刚好就可以与栈中的左括号进行匹配,如果正确,就把左括坏出栈

  3. 如果最终栈为空,说明全部匹配成功

那代码实现起来的逻辑就很简单了

遍历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.lengthstack.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

image-20190808164625965