算法练习 - 02 括号匹配

326 阅读1分钟

问题描述

对一串字符串进行匹配括号是否匹配,例如 "{a(g[c]f)d}"符号的顺序以及数量都是匹配的,"{a[b(d]d}" 括号是不匹配的

问题解析

算法matchBracket

  • 定义空栈用于存在左右符号
  • 循环字符串拿出当前字符
  • 在左括号中存在就push进队列中
  • 在右括号中进行匹配,如果包含就拿出栈中最后进入的符号进行匹配,如果不匹配就代表整个字符串不匹配
  • 返回最后的栈是否长度为0,0代表匹配,否则就是不匹配

算法复杂度

  • 时间复杂度: O(n) 单次循环
  • 空间复杂度: O(n) stack占用空间
/**
 * 括号匹配
 * 对一串字符串进行匹配括号是否匹配,例如  "{a(g[c]f)d}" 符号的顺序以及数量都是匹配的,"{a[b(d]d}" 括号是不匹配的
 */
export function matchBracket(str: string): boolean {
    let length = str.length;
    if (length === 0) return true;
    // 定义左括号字符串
    let leftSybmol = "{[(";
    // 定义右括号字符串
    let rightSybmol = "}])";
    // 定义栈队列
    let stack = [];
    // 循环获取当前匹配字符内容
    for (let i = 0; i < length; i++) {
        let s = str[i];
        // 如果左括号包含
        if (leftSybmol.includes(s)) {
            stack.push(s);
        //如果右括号包含
        } else if (rightSybmol.includes(s)) {
            // 获取当前栈队列中最顶部的符号
            let top = stack[stack.length - 1];
            // 进行匹配校验
            if (isMatch(top, s)) {
                stack.pop();
            } else {
                return false;
            }
        }
    }
    // 返回最后的栈是否长度为0,0代表匹配,否则就是不匹配
    return stack.length === 0;
}
/**
 * 判断左括号和右括号是否匹配
 * @param left 左括号
 * @param right 右括号
 * @returns 是否匹配
 */
function isMatch(left: string, right: string): boolean {
    if (left === "(" && right === ")") return true;
    if (left === "[" && right === "]") return true;
    if (left === "{" && right === "}") return true;
    return false;
}

测试算法

测试算法正确性

/**
 * 测试代码
 */
 (function () {
    const str = "{x(k[l]j)y}";
    console.log(MatchBracket(str));
})();

测试结果图

iShot_2022-05-22_22.51.59.png

测试用例

  • 测试正常数据下结果
  • 测试空字符串
  • 测试右括号不匹配
  • 测试左括号不匹配
  • 测试右括号开头
/**
 * 括号匹配单元测试
 */

import { MatchBracket } from "./match-bracket";
describe("括号匹配单元测试", () => {
    it("正常情况", () => {
        const str = "{x(k[l]j)y}";
        let result = MatchBracket(str);
        expect(result).toBe(true);
    });
    it("空字符串", () => {
        const str = "";
        let result = MatchBracket(str);
        expect(result).toBe(true);
    });
    it("右括号不匹配", () => {
        const str = "{x(k[l]y)j)y";
        let result = MatchBracket(str);
        expect(result).toBe(false);
    });
    it("左括号不匹配", () => {
        const str = "x(k[l]y)j)y}";
        let result = MatchBracket(str);
        expect(result).toBe(false);
    });
    it("右括号开头", () => {
        const str = "}{x(k[l]y)j)y}";
        let result = MatchBracket(str);
        expect(result).toBe(false);
    });
});