算法:判断字符串是否括号匹配

41 阅读1分钟

问题

  • 一个字符串s可能包含{}()[]三种括号
  • 判断s是否是括号匹配的
  • 如(a{b}c)匹配,而{a(b或{a(b}c)就不匹配

  • 先进后出
  • API: push pop length
  • 相关的:队列,堆

image.png

逻辑结构 vs 物理结构

  • 栈 vs 数组
  • 栈,逻辑结构。理论模型,不管如何实现,不受任何语言的限制
  • 数组,物理结构。真实的功能实现,受限于编程语言

思路

  • 遇到左括号{([就压栈
  • 遇到右括号})]就判断栈顶,匹配则出栈
  • 最后判断length是否为0

image.png

代码

function isMatch(left: string, right: string): boolean {
  if (left === '{' && right === '}') return true
  if (left === '[' && right === ']') return true
  if (left === '(' && right === ')') return true
  return false
}

// O(n)
export function matchBracket(str: string): boolean {
  const length = str.length

  if (length === 0) return true
  const stack: string[] = []

  const leftSymbols = '{[('
  const rightSymbols = '}])'

  for (let i = 0; i < length; i++) {
    const s: string = str[i]
    if (leftSymbols.includes(s)) {
      // 左括号 压栈
      stack.push(s)
    } else if (rightSymbols.includes(s)) {
      // 右括号判断栈顶 (是否出栈)
      const top = stack[stack.length - 1]
      if (isMatch(top, s)) {
        stack.pop()
      } else {
        return false
      }
    }
  }
  return stack.length === 0
}

// 功能测试
const str = '{a(b[c]d)e}f'
console.log(matchBracket(str))

image.png

jest单元测试

import { matchBracket } from './判断一个字符串是否括号匹配'

describe('括号匹配', () => {
  it('正常情况', () => {
    const str = '{a(b[c]d)e}f'
    const res = matchBracket(str)
    expect(res).toBe(true)
  })
  it('不匹配', () => {
    const str = '{a(b[c)]d)e}f'
    const res = matchBracket(str)
    expect(res).toBe(false)
  })

  it('顺序不一致的', () => {
    const str = '{a(b[c]d}e)f'
    const res = matchBracket(str)
    expect(res).toBe(false)
  })
  it('空字符串', () => {
    const res = matchBracket('')
    expect(res).toBe(false)
  })
})