[Algorithm Challenge] Design a stack that supports incremental operations (including parsing and source code)

1381. Design a stack that supports incremental operations

https://leetcode-cn.com/problems/design-a-stack-with-increment-operation/

  • 1381. Design a stack that supports incremental operations
    • Question description
    • Method 1: Use an array or linked list to simulate a stack
      • array
      • Complexity analysis
      • linked list
      • Complexity analysis
      • code
    • Method 2: Exchange space for time
      • Illustration
      • Complexity analysis
      • code

Title description

Please design a stack that supports the following operations.

Implement the custom stack class CustomStack:

CustomStack(int maxSize): Initialize the object with maxSize. maxSize is the maximum number of elements that can be accommodated in the stack. The stack does not support push operations after it grows to maxSize.
void push(int x): If the stack has not grown to maxSize, add x to the top of the stack.
int pop(): Pops the top element of the stack and returns the value on the top of the stack, or -1 when the stack is empty.
void inc(int k, int val): The values of the k elements at the bottom of the stack are increased by val. If the total number of elements in the stack is less than k, then all elements in the stack are incremented by val.
 

Example:

enter:
["CustomStack","push","push","pop","push","push","push","increment",\ "increment","pop","pop","pop","pop"]
[[3],[1],[2],[],[2],[3],[4],[5,100],[2,100],[],[],[],[]]
Output:
[null,null,null,2,null,null,null,null,null,103,202,201,-1]
explain:
CustomStack customStack = new CustomStack(3); // The stack is empty []
customStack.push(1); // The stack becomes [1]
customStack.push(2); // The stack becomes [1, 2]
customStack.pop(); // Return 2 --> Return the top value of the stack 2, and the stack becomes [1]
customStack.push(2); // The stack becomes [1, 2]
customStack.push(3); // The stack becomes [1, 2, 3]
customStack.push(4); // The stack is still [1, 2, 3], no other elements can be added to make the stack size 4
customStack.increment(5, 100); // The stack becomes [101, 102, 103]
customStack.increment(2, 100); // The stack becomes [201, 202, 103]
customStack.pop(); // Return 103 --> Return the top value of the stack 103, and the stack becomes [201, 202]
customStack.pop(); // Return 202 --> Return the top value of the stack 202, and the stack becomes [201]
customStack.pop(); // Return 201 --> Return the top value of the stack 201, and the stack becomes []
customStack.pop(); // Return -1 --> If the stack is empty, return -1
 

hint:

1 <= maxSize <= 1000
1 <= x <= 1000
1 <= k <= 1000
0 <= val <= 100
Each method increment, push and pop can be called up to 1000 times each.

Source: LeetCode
Link: https://leetcode-cn.com/problems/design-a-stack-with-increment-operation
The copyright belongs to Lingkou Network. For commercial reprinting, please contact the official authorizer. For non-commercial reprinting, please indicate the source.

Method 1: Use array or linked list to simulate stack

Array

Using arrays to simulate stacks can achieve time complexity

O

(

1

)

O(1)

O(1) for push and pop, and

O

(

k

)

O(k)

O(k) inc, the rest can be implemented as per the title description.

  • When the number of stack elements is equal to maxSize, it is not allowed to continue pushing onto the stack;
  • When the stack is empty, the pop operation returns -1;
  • During incremental operation, when the stack elements are more than k, add val to the k elements at the bottom of the stack, and the stack elements are less than k At this time, add val to all elements.

Complexity analysis

  • Time complexity: push and pop are

    O

    (

    1

    )

    O(1)

    O(1), inc is

    O

    (

    k

    )

    O(k)

    O(k).

  • Space complexity:

    O

    (

    m

    a

    x

    S

    i

    z

    e

    )

    O(maxSize)

    O(maxSize).

Linked list

You can also use a linked list to simulate a stack. Pushing and popping out of the stack only operates head, which can also achieve time complexity.

O

(

1

)

O(1)

The push and pop operations are O(1), but for the inc operation, the k< from the end of the linked list is found. The time complexity of /code> elements (can be found using double pointers) is

O

(

n

)

O(n)

O(n), then the time complexity of incrementing the k elements at the end of the linked list is

O

(

k

)

O(k)

O(k), so the total time complexity of the incremental operation is

O

(

n

+

k

)

O(n + k)

O(n + k).

Complexity analysis

  • Time complexity: push and pop are

    O

    (

    1

    )

    O(1)

    O(1), inc is

    O

    (

    n

    +

    k

    )

    O(n + k)

    O(n + k).

  • Space complexity:

    O

    (

    m

    a

    x

    S

    i

    z

    e

    )

    O(maxSize)

    O(maxSize).

Code

JavaScript Code

/**
 * @param {number} maxSize
 */
var CustomStack = function (maxSize) {<!-- -->
    this.list = [];
    this.maxSize = maxSize;
};

/**
 * @param {number} x
 * @return {void}
 */
CustomStack.prototype.push = function (x) {<!-- -->
    if (this.list.length <this.maxSize) {<!-- -->
        this.list.push(x);
    }
};

/**
 * @return {number}
 */
CustomStack.prototype.pop = function () {<!-- -->
    const item = this.list.pop();
    return item === void 0 ? -1 : item;
};

/**
 * @param {number}k
 * @param {number} val
 * @return {void}
 */
CustomStack.prototype.increment = function (k, val) {<!-- -->
    for (let i = 0; i < k & amp; & amp; i <this.list.length; i + + ) {<!-- -->
        this.list[i] + = val;
    }
};

/**
 * Your CustomStack object will be instantiated and called as such:
 * var obj = new CustomStack(maxSize)
 * obj.push(x)
 * var param_2 = obj.pop()
 * obj.increment(k,val)
 */

Python Code

class CustomStack(object):

    def __init__(self, maxSize):
        """
        :type maxSize: int
        """
        self.list = []
        self.maxSize = maxSize

    def size(self):
        return len(self.list)


    def push(self, x):
        """
        :type x: int
        :rtype: None
        """
        if self.size() < self.maxSize:
            self.list.append(x)


    def pop(self):
        """
        :rtype: int
        """
        return -1 if self.size() == 0 else self.list.pop()


    def increment(self, k, val):
        """
        :type k: int
        :type val: int
        :rtype: None
        """
        size = k if k < self.size() else self.size()
        for i in range(0, size):
            self.list[i] + = val



# Your CustomStack object will be instantiated and called as such:
# obj = CustomStack(maxSize)
# obj.push(x)
# param_2 = obj.pop()
# obj.increment(k,val)

Method 2: Exchange space for time

In fact, we only care about the value of the element when popping it off the stack, so during incremental operations, we don't need to update the elements in the stack. Instead, we use a hashMap to record the number of elements that need to be added. When popping off the stack, check whether the subscript of the current element is recorded in the hashMap. If so, add the increment before popping it off the stack. This way we get the time complexity

O

(

1

)

O(1)

O(1) incremental operation, but the price is extra

O

(

N

)

O(N)

O(N) space.

Illustration

Complexity analysis

  • Time complexity: push, pop and inc are all

    O

    (

    1

    )

    O(1)

    O(1).

  • Space complexity:

    O

    (

    m

    a

    x

    S

    i

    z

    e

    )

    O(maxSize)

    O(maxSize), the space of the simulated stack array and hash table is

    O

    (

    m

    a

    x

    S

    i

    z

    e

    )

    O(maxSize)

    O(maxSize).

Code

JavaScript Code

/**
 * @param {number} maxSize
 */
var CustomStack = function (maxSize) {<!-- -->
    this.list = [];
    this.maxSize = maxSize;
    this.hashMap = {<!-- -->};
};

/**
 * @param {number} key
 * @param {number} value
 * @return {void}
 */
CustomStack.prototype._setInc = function (key, value) {<!-- -->
    if (!(key in this.hashMap)) {<!-- -->
        this.hashMap[key] = 0;
    }
    this.hashMap[key] + = value;
};

/**
 * @param {number} key
 * @return {number}
 */
CustomStack.prototype._getInc = function (key) {<!-- -->
    return this.hashMap[key] || 0;
};

/**
 * @return {number}
 */
CustomStack.prototype._size = function () {<!-- -->
    return this.list.length;
};

/**
 * @param {number} x
 * @return {void}
 */
CustomStack.prototype.push = function (x) {<!-- -->
    if (this._size() <this.maxSize) {<!-- -->
        this.list.push(x);
    }
};

/**
 * @return {number}
 */
CustomStack.prototype.pop = function () {<!-- -->
    const top = this._size() - 1;
    const inc = this._getInc(top);

    let item = this.list.pop();
    if (item === void 0) {<!-- -->
        return -1;
    }

    item + = inc;
    const newTop = top - 1;
    this._setInc(newTop, inc);
    this.hashMap[top] = 0;
    return item;
};

/**
 * @param {number}k
 * @param {number} val
 * @return {void}
 */
CustomStack.prototype.increment = function (k, val) {<!-- -->
    const size = this._size();
    k = k < size ? k - 1 : size - 1;
    this._setInc(k, val);
};

/**
 * Your CustomStack object will be instantiated and called as such:
 * var obj = new CustomStack(maxSize)
 * obj.push(x)
 * var param_2 = obj.pop()
 * obj.increment(k,val)
 */

Summary

The above is the entire content of this article. I hope it will be helpful to you and solve the problem of designing a stack that supports incremental operations.

If you like this article, please be sure to like, collect, comment, and forward it, it will be of great help to me. It would also be great to buy me a glass of iced Coke!

It has been completed, please continue to pay attention. See you next time~

syntaxbug.com © 2021 All Rights Reserved.