threedayAAAAA / alg-exercise

算法训练
0 stars 0 forks source link

【基础篇 - Day 3】 2023-02-15 - 1381. 设计一个支持增量操作的栈 (01. 数组,栈,队列 ) #5

Open threedayAAAAA opened 1 year ago

threedayAAAAA commented 1 year ago

请你设计一个支持对其元素进行增量操作的栈。

实现自定义栈类 CustomStack :

CustomStack(int maxSize):用 maxSize 初始化对象,maxSize 是栈中最多能容纳的元素数量。 void push(int x):如果栈还未增长到 maxSize ,就将 x 添加到栈顶。 int pop():弹出栈顶元素,并返回栈顶的值,或栈为空时返回 -1 。 void inc(int k, int val):栈底的 k 个元素的值都增加 val 。如果栈中元素总数小于 k ,则栈中的所有元素都增加 val 。  

示例:

输入: ["CustomStack","push","push","pop","push","push","push","increment","increment","pop","pop","pop","pop"] [[3],[1],[2],[],[2],[3],[4],[5,100],[2,100],[],[],[],[]] 输出: [null,null,null,2,null,null,null,null,null,103,202,201,-1] 解释: CustomStack stk = new CustomStack(3); // 栈是空的 [] stk.push(1); // 栈变为 [1] stk.push(2); // 栈变为 [1, 2] stk.pop(); // 返回 2 --> 返回栈顶值 2,栈变为 [1] stk.push(2); // 栈变为 [1, 2] stk.push(3); // 栈变为 [1, 2, 3] stk.push(4); // 栈仍然是 [1, 2, 3],不能添加其他元素使栈大小变为 4 stk.increment(5, 100); // 栈变为 [101, 102, 103] stk.increment(2, 100); // 栈变为 [201, 202, 103] stk.pop(); // 返回 103 --> 返回栈顶值 103,栈变为 [201, 202] stk.pop(); // 返回 202 --> 返回栈顶值 202,栈变为 [201] stk.pop(); // 返回 201 --> 返回栈顶值 201,栈变为 [] stk.pop(); // 返回 -1 --> 栈为空,返回 -1  

提示:

1 <= maxSize, x, k <= 1000 0 <= val <= 100 每种方法 increment,push 以及 pop 分别最多调用 1000 次

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/design-a-stack-with-increment-operation 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

threedayAAAAA commented 1 year ago

方法一

思路

直接使用js的数组模拟即可,只不过注意一下每个操作的边界

代码

class CustomStack {
    private data: number[]
    private maxSize: number

    constructor(maxSize: number) {
        this.data = []
        this.maxSize = maxSize
    }

    push(x: number): void {
        if(this.data.length >=  this.maxSize){
            return
        }
        this.data.push(x)
    }

    pop(): number {
        if(this.data.length){
            return this.data.pop()
        } else {
            return -1
        }
    }

    increment(k: number, val: number): void {
        const maxIndex = Math.min(k, this.data.length)
        for(let i = 0; i < maxIndex; i++){
            this.data[i] += val
        }
    }
}

时空复杂度

方法二

思路

代码

class CustomStack {
    private data: number[]
    private addStack: number[]
    private maxSize: number

    constructor(maxSize: number) {
        this.data = []
        this.addStack = new Array(maxSize).fill(0)
        this.maxSize = maxSize
    }

    push(x: number): void {
        if(this.data.length >=  this.maxSize){
            return
        }
        this.data.push(x)
    }

    pop(): number {
        if(this.data.length){
            const targetIndex = this.data.length - 1
            const lastAdd = this.addStack[targetIndex]
            if(targetIndex > 0){
                this.addStack[targetIndex - 1] += lastAdd
            }
            this.addStack[targetIndex] = 0
            return this.data.pop() + lastAdd
        } else {
            return -1
        }
    }

    increment(k: number, val: number): void {
        const maxIndex = Math.min(k, this.data.length) - 1
        this.addStack[maxIndex] += val
    }
}

时空复杂度

方法三

思路

通过分析方法二 可以发现没必要一开始就把辅助空间设置到 maxSize 这么大 , 因为在栈内的值未到 maxSize时会照成空间浪费 所以在方法二的基础上进行优化 将辅助空间的大小初始化为空 在push 跟pop时同步维护即可 这样辅助空间不会有多余的浪费

代码

class CustomStack {
    private data: number[]
    private addStack: number[]
    private maxSize: number

    constructor(maxSize: number) {
        this.data = []
        this.addStack = []
        this.maxSize = maxSize
    }

    push(x: number): void {
        if(this.data.length >=  this.maxSize){
            return
        }
        this.data.push(x)
        this.addStack.push(0)
    }

    pop(): number {
        if(this.data.length){
            const targetIndex = this.data.length - 1
            const lastAdd = this.addStack[targetIndex]
            if(targetIndex > 0){
                this.addStack[targetIndex - 1] += lastAdd
            }
            return this.data.pop() + this.addStack.pop()
        } else {
            return -1
        }
    }

    increment(k: number, val: number): void {
        const maxIndex = Math.min(k, this.data.length) - 1
        this.addStack[maxIndex] += val
    }
}

时空复杂度

yunliuyan commented 1 year ago

方法1

思路

代码

class CustomStack {
    maxSize: number;
    stack: number[];
    constructor(maxSize: number) {
        this.maxSize = maxSize;
        this.stack = [];
    }

    push(x: number): void {
        if(this.stack.length === this.maxSize) {
            return;
        }
        this.stack.push(x);
    }

    pop(): number {
        if (!this.stack.length) {
            return -1;
        }
        return this.stack.pop();
    }

    increment(k: number, val: number): void {
        for (let i = 0; i < k; i++) {
            if (i === this.stack.length) {
                break;
            }
            this.stack[i] += val;
        }
    }
}

时空复杂度

时间复杂度: O(k) 空间复杂度:O(maxSize)

方法2

思路

代码

class CustomStack {
    maxSize: number;
    stack: number[];
    incStack: number[];
    constructor(maxSize: number) {
        this.maxSize = maxSize;
        this.stack = [];
        this.incStack = [];
    }

    push(x: number): void {
        if (this.stack.length === this.maxSize) {
            return
        }
        this.stack.push(x);
        this.incStack.push(0);
    }

    pop(): number {
       const len = this.stack.length;
       if(len === 0) {
           return -1
       } 
       if (len > 1) {
           this.incStack[len - 2] += this.incStack[len - 1];
       }
       return this.stack.pop() + this.incStack.pop();
    }

    increment(k: number, val: number): void {
        const limit = Math.min(k - 1, this.stack.length - 1);
        this.incStack[limit] += val;
    }
}

时空复杂度

时间复杂度: O(1) 空间复杂度: O(N)

MiumMi commented 1 year ago

思路

js数组原生方法实现即可

代码

class CustomStack {
    arr: number[];
    maxSize: number = 0;
    constructor(maxSize: number) {
        this.maxSize = maxSize;
        this.arr = [];
    }

    push(x: number): void {
        if (this.arr.length >= this.maxSize) {
            return;
        }
        this.arr.push(x);
    }

    pop(): number {
        if (this.arr.length <= 0) {
            return -1;
        }
        return this.arr.pop();
    }

    increment(k: number, val: number): void {
        const arr = this.arr;
        const size = Math.min(arr.length, k);
        for (let i = 0; i < size; i++) {
            arr[i] += val;
        }
    }
}

复杂度分析:

  1. 时间复杂度:pop,push为O(1), inc为O(n)
  2. 空间复杂度:O(1)