刷题Day09

文章介绍了如何使用栈和队列数据结构实现各种算法,如队列模拟栈、栈模拟队列、有效括号检查、删除重复字符、逆波兰表达式求值、滑动窗口最大值以及找出前k个高频元素。
摘要由CSDN通过智能技术生成

01.用栈实现队列

思路:使用两个栈实现队列功能

class MyQueue {
    private stackIn:number[];
    private stackOut:number[];
    constructor() {
        this.stackIn = []
        this.stackOut = []
    }

    push(x: number): void {
        this.stackIn.push(x)
    }

    pop(): number {
        this.stackOut.push(...this.stackIn)
        this.stackIn = []
        let tmp = this.stackOut.splice(0,1)
        return tmp[0]
    }

    peek(): number {
        this.stackOut.push(...this.stackIn)
        this.stackIn = []
        return this.stackOut[0]
    }

    empty(): boolean {
        console.log(this.stackIn, this.stackOut)
        if (this.stackIn.length == 0 && this.stackOut.length == 0) return true
        return false
    }
}

02.用队列实现栈

 思路:。。。

class MyStack {
    private queue:number[];
    constructor() {
        this.queue = []
    }

    push(x: number): void {
        this.queue.push(x)
    }

    pop(): number {
        return this.queue.splice(this.queue.length - 1)[0]
    }

    top(): number {
        return this.queue[this.queue.length - 1]
    }

    empty(): boolean {
        if (this.queue.length == 0) return true
        return false
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * var obj = new MyStack()
 * obj.push(x)
 * var param_2 = obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.empty()
 */

03.有效的括号

思路:利用栈后入先出的特性,遍历字符串

function isValid(s: string): boolean {
    let stack:string[] = []
    for (let i = 0; i < s.length; i++) {
        switch (s[i]) {
            case '(': stack.push(')');break
            case '{': stack.push('}');break
            case '[': stack.push(']');break
            default: if (s[i] != stack.pop())return false
        }
    }
    return stack.length == 0
};

04.删除字符串中的所有相邻重复项

思路:利用栈后入先出的特性,与栈最后一个字符做对比,相同则去除最后一位,否则,将该字符加入栈中

function removeDuplicates(s: string): string {
    let stack:string[] = []
    for (let i = 0; i < s.length; i++) {
        if (s[i] == stack[stack.length - 1]) {
            stack.pop()
        } else {
            stack.push(s[i])
        }
    }
    return stack.join('')
};

05.逆波兰表达式求值

思路:当遇到运算符时,取出栈中最后两位计算,并将结果推入栈中

function evalRPN(tokens: string[]): number {
    let stack:number[] = []
    let tmp
    for (let i = 0; i < tokens.length; i++) {
        switch (tokens[i]) {
            case '+' :
                tmp = stack.pop()
                stack.push(tmp! + stack.pop()!)
                break;
            case '-' :
                tmp = stack.pop()
                stack.push(stack.pop()! - tmp!)
                break;
            case '*' :
                stack.push(stack.pop()! * stack.pop()!)
                break
            case '/' :
                tmp = stack.pop()
                stack.push(Math.trunc(stack.pop()! / tmp!))
                break
            default: 
                stack.push(+tokens[i])
                break
        }
    }
    return stack.pop()
};

06. 滑动窗口最大值*

思路:使用单调队列。在本题中为单调递减队列。入列的条件:大于队尾元素或者队列为空。出列:当窗口的的第一个值等于队头元素时出列。

单调队列真是一种让人感到五味杂陈的数据结构,它的维护过程更是如此.....就拿此题来说,队头最大,往队尾方向单调......有机会站在队头的老大永远心狠手辣,当它从队尾杀进去的时候,如果它发现这里面没一个够自己打的,它会毫无人性地屠城,把原先队里的人头全部丢出去,转身建立起自己的政权,野心勃勃地准备开创一个新的王朝.....这时候,它的人格竟发生了一百八十度大反转,它变成了一位胸怀宽广的慈父!它热情地请那些新来的“小个子”们入住自己的王国......然而,这些小个子似乎天性都是一样的——嫉妒心强,倘若见到比自己还小的居然更早入住王国,它们会心狠手辣地找一个夜晚把它们通通干掉,好让自己享受更大的“蛋糕”;当然,遇到比自己强大的,它们也没辙,乖乖夹起尾巴做人。像这样的暗杀事件每天都在上演,虽然王国里日益笼罩上白色恐怖,但是好在没有后来者强大到足以干翻国王,江山还算能稳住。直到有一天,闯进来了一位真正厉害的角色,就像当年打江山的国王一样,手段狠辣,野心膨胀,于是又是大屠城......历史总是轮回的。

                                                                                                ---- leetcode用户:虫子的世界

function maxSlidingWindow(nums: number[], k: number): number[] {
    class MonoQueue {
        private queue:number[];
        constructor () {
            this.queue = []
        }

        public enqueue (value:number) {
            let back: number | undefined = this.queue[this.queue.length - 1]
            while (back != undefined && back < value) {
                this.queue.pop()
                back = this.queue[this.queue.length - 1]
            }
            this.queue.push(value)
        }

        public dequeue (value:number) {
            let top:number | undefined = this.top()
            if (top != undefined && top == value) {
                this.queue.shift()
            }
        }

        public top ():number | undefined{
            return this.queue[0]
        }
    }

    const helperQueue: MonoQueue = new MonoQueue();
    let i: number = 0,
        j: number = 0;
    let resArr: number[] = [];
    while (j < k) {
        helperQueue.enqueue(nums[j++]);
    }
    resArr.push(helperQueue.top()!);
    while (j < nums.length) {
        helperQueue.enqueue(nums[j]);
        helperQueue.dequeue(nums[i]);
        resArr.push(helperQueue.top()!);
        j++, i++;
    }
    return resArr;
};

 07.前 K 个高频元素

思路:使用map记录元素及其出现次数。然后将map结构成数组,降序排序并且截取前k个

function topKFrequent(nums: number[], k: number): number[] {
    let frequentMap:Map<number, number> = new Map()
    for (let num of nums) {
        frequentMap.set(num, (frequentMap.get(num) || 0) + 1)
    }
    console.log(...frequentMap.entries())
    return [...frequentMap.entries()].sort((a, b) => b[1] - a[1]).slice(0, k).map(i=>i[0])
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值