栈和队列

105 阅读2分钟
用链表实现队列
  1. 声明 head 和 tail
  2. add 是入队,先把传入的数据包成一个节点,如果 head 为空,head 就为新节点,tail也是新节点,如果tail有值,newNode 赋给 tail.next,这样新入的排在链表末端
  3. delete 出队,取出 head的值,再把 this.head 指向 head.next
interface IListNode {
    value: number
    next: IListNode | null
}

export class Queue {
    private head: IListNode | null = null
    private tail: IListNode | null = null
    private len = 0

    /**
     * 入队,在 tail 位置
     * @param n number
     */
    add(n: number) {
        const newNode: IListNode = {
            value: n,
            next: null,
        }

        // 处理 head
        if (this.head == null) {
            this.head = newNode
        }

        // 处理 tail
        const tailNode = this.tail
        if (tailNode) {
            tailNode.next = newNode
        }
        this.tail = newNode

        // 记录长度
        this.len++
    }

    /**
     * 出队,在 head 位置
     */
    delete(): number | null {
        const headNode = this.head
        if (headNode == null) return null
        if (this.len <= 0) return null

        // 取值
        const value = headNode.value

        // 处理 head
        this.head = headNode.next

        // 记录长度
        this.len--

        return value
    }

    get length(): number {
        // length 要单独存储,不能遍历链表来获取(否则时间复杂度太高 O(n))
        return this.len
    }
}
两个栈实现一个队列
  1. 入队列直接 stack1.push(n)
  2. 出队列,stack1 的元素全挪到 stack2, 拿到 stack2.pop 的结果,再把 stack2 全挪到 stack1
class Queue {
    private stack1: number[] = []
    private stack2: number[] = []

    /**
     * 入队
     * @param n n
     */
    add(n: number) {
        this.stack1.push(n)
    }

    /**
     * 出队
     */
    delete(): number | null {
        let res

        const stack1 = this.stack1
        const stack2 = this.stack2

        // 将 stack1 所有元素移动到 stack2 中
        while(stack1.length) {
            const n = stack1.pop()
            if (n != null) {
                stack2.push(n)
            }
        }

        // stack2 pop
        res = stack2.pop()

        // 将 stack2 所有元素“还给”stack1
        while(stack2.length) {
            const n = stack2.pop()
            if (n != null) {
                stack1.push(n)
            }
        }

        return res || null
    }

    get length(): number {
        return this.stack1.length
    }
}

判断字符串里的括号是否正确成对匹配
  1. 先声明左右的符号集 left = '{[(' right = '}])'
  2. 遍历字符串,如果字符属于左集就压栈
  3. 如果属于右集,先判断栈头部的(刚才压入的)与当前的字符是否成对,如果成对就出栈,如果不成对,证明不匹配
  4. 遍历过后,如果栈空了,表明都能正确成对匹配,如果不空表示不能正确配对。

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 matchBracket(str: string): boolean {
    const length = str.length
    if (length === 0) return true

    const stack = []
    
    const left = '{[('
    const right = '}])'

    for (let i = 0; i < length; i++) {
        const txt = str[i]

        if (left.includes(s)) {
            // 左括号,压栈
            stack.push(s)
        } else if (right.includes(txt)) {
            // 右括号,判断栈顶(是否出栈)
            const top = stack[stack.length - 1]
            if (isMatch(top, txt)) {
                stack.pop()
            } else {
                return false
            }
        }
    }

    return stack.length === 0
}