题目

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

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。


思路分析

判断括号的有效性,可以使用 「 栈 」这一数据结构来解决。

  1. 判断括号的有效性的一个前提条件是字符串的长度一定为偶数,如果字符串长度为奇数,说明括号是无效的,我们直接返回 false,省去后续遍历判断过程。
  2. 为了快速判断括号的类型,我们使用字典(也称映射)这一数据结构存储每一种括号。字典的键为左括号,值为右括号。另外使用数组来模拟栈结构。
  3. 对给定的字符串进行遍历,当我们遇到一个左括号时,我们期望在后续的遍历中,会有一个相同类型的右括号将其闭合,因此我们可以先将这个左括号放入栈中。当我们遇到一个右括号时,我们需要一个相同类型的左括号闭合,此时,我们可以取出栈顶的左括号并判断它们是否是相同类型的括号。如果不是相同的类型,或者栈中并没有左括号,那么字符串是无效的,返回 false。
  4. 在遍历结束后,如果栈中没有元素,说明字符串中的所有左括号都有与之对应的右括号将其闭合,也就是我们要判断的字符串是有效的,返回 true,否则返回 false。

baa8829ac398e665eb645dca29eadd631e2b337e05022aa5a678e091471a4913-20.gif

代码实现

使用ES6的Map存储括号

  1. /**
  2. *@param {string} s
  3. *@return {boolean}
  4. */
  5. var isValid = function(s) {
  6. const len = s.length;
  7. // 判断字符串长度是否为偶数,如果为奇数,则字符串无效,返回false
  8. if (len % 2 === 1) return false;
  9. // 使用数组模拟栈结构
  10. const stack = [];
  11. // 使用 Map 存储括号
  12. const map = new Map([['(', ')'], ['[', ']'], ['{', '}']]);
  13. for (let i = 0; i < len; i++) {
  14. const str = s[i];
  15. if (map.has(str)) {
  16. // 是左括号,则入栈
  17. stack.push(str)
  18. } else {
  19. if (str != map.get(stack.pop())) {
  20. // 此时遇到的是右括号,出栈的左括号与右括号不是同类型的括号,或者栈中没有左括号,
  21. // 说明字符串是无效的,返回 false,结束后续循环
  22. return false
  23. }
  24. }
  25. }
  26. // 遍历结束后,如果栈为空,说明字符串是有效的,返回 true,否则返回 false
  27. return !stack.length
  28. }

使用Object存储括号

  1. /**
  2. *@param {string} s
  3. *@return {boolean}
  4. */
  5. var isValid = function(s) {
  6. const len = s.length;
  7. // 判断字符串长度是否为偶数,如果为奇数,则字符串无效,返回false
  8. if (len % 2 === 1) return false;
  9. // 使用数组模拟栈结构
  10. const stack = [];
  11. // 使用对象(字典)存储括号
  12. const map = {
  13. '(': ')',
  14. '[': ']',
  15. '{': '}'
  16. }
  17. for (let i = 0; i < s.length; i++) {
  18. const str = s[i];
  19. if (str in map) {
  20. // 是左括号,则入栈
  21. stack.push(str)
  22. } else {
  23. if (str != map[stack.pop()]) {
  24. // 此时遇到的是右括号,出栈的左括号与右括号不是同类型的括号,或者栈中没有左括号,
  25. // 说明字符串是无效的,返回 false,结束后续循环
  26. return false
  27. }
  28. }
  29. }
  30. // 遍历结束后,如果栈为空,说明字符串是有效的,返回 true,否则返回 false
  31. return !stack.length
  32. }