题目是LeetCode第180场周赛的第二题,链接:设计一个支持增量操作的栈。具体描述为:请你设计一个支持下述操作的栈。实现自定义栈类 CustomStack :
- CustomStack(int maxSize):用 maxSize 初始化对象,maxSize 是栈中最多能容纳的元素数量,栈在增长到 maxSize 之后则不支持 push 操作。
- 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 customStack = new CustomStack(3); // 栈是空的 []
customStack.push(1); // 栈变为 [1]
customStack.push(2); // 栈变为 [1, 2]
customStack.pop(); // 返回 2 --> 返回栈顶值 2,栈变为 [1]
customStack.push(2); // 栈变为 [1, 2]
customStack.push(3); // 栈变为 [1, 2, 3]
customStack.push(4); // 栈仍然是 [1, 2, 3],不能添加其他元素使栈大小变为 4
customStack.increment(5, 100); // 栈变为 [101, 102, 103]
customStack.increment(2, 100); // 栈变为 [201, 202, 103]
customStack.pop(); // 返回 103 --> 返回栈顶值 103,栈变为 [201, 202]
customStack.pop(); // 返回 202 --> 返回栈顶值 202,栈变为 [201]
customStack.pop(); // 返回 201 --> 返回栈顶值 201,栈变为 []
customStack.pop(); // 返回 -1 --> 栈为空,返回 -1
虽然是个medium难度的题目,但其实还是蛮简单的,可以直接用一个数组和一个指向栈顶的索引来实现所有的功能。需要注意的就以下几点:
- push的时候注意超过maxSize时不做任何操作;
- pop的时候注意栈空的话返回-1;
- increment的时候注意不要超过maxSize。
除了increment操作的时间复杂度为 O ( m i n ( n , k ) ) O(min(n,k)) O(min(n,k))(其中n为栈长度),其余操作的时间复杂度均为 O ( 1 ) O(1) O(1),空间复杂度为 O ( n ) O(n) O(n)。
JAVA版代码如下:
class CustomStack {
private int[] stack;
private int length;
private int maxSize;
public CustomStack(int maxSize) {
stack = new int[maxSize];
length = 0;
this.maxSize = maxSize;
}
public void push(int x) {
if (length < this.maxSize) {
stack[length++] = x;
}
}
public int pop() {
if (length > 0) {
return stack[--length];
}
return -1;
}
public void increment(int k, int val) {
k = k > length ? length : k;
for (int i = 0; i < k; ++i) {
stack[i] += val;
}
}
}
/**
* Your CustomStack object will be instantiated and called as such:
* CustomStack obj = new CustomStack(maxSize);
* obj.push(x);
* int param_2 = obj.pop();
* obj.increment(k,val);
*/
提交结果如下:
Python版代码如下:
class CustomStack:
def __init__(self, maxSize: int):
self.stack = [0 for _ in range(maxSize)]
self.maxSize = maxSize
self.length = 0
def push(self, x: int) -> None:
if self.length < self.maxSize:
self.stack[self.length] = x
self.length += 1
def pop(self) -> int:
if self.length > 0:
self.length -= 1
return self.stack[self.length]
return -1
def increment(self, k: int, val: int) -> None:
k = self.length if self.length < k else k
for i in range(k):
self.stack[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)
提交结果如下:
然后从leetcode评论区又看到一种方法,可以将increment操作的复杂度也降到 O ( 1 ) O(1) O(1),只要的想法来源是说没有必要每次increment的时候都将栈中元素真的增加一个值,只需要用另外一个栈记录需要增加的值,在pop的时候把需要增加的值给加上去就好了。
JAVA版代码如下:
class CustomStack {
private int[] stack;
private int[] inc;
private int length;
private int maxSize;
public CustomStack(int maxSize) {
stack = new int[maxSize];
inc = new int[maxSize];
length = 0;
this.maxSize = maxSize;
}
public void push(int x) {
if (length < this.maxSize) {
stack[length++] = x;
}
}
public int pop() {
if (length > 0) {
--length;
int result = stack[length] + inc[length];
if (length - 1 >= 0) {
inc[length - 1] += inc[length];
}
inc[length] = 0;
return result;
}
return -1;
}
public void increment(int k, int val) {
k = k > length ? length : k;
if (k > 0) {
inc[k - 1] += val;
}
}
}
/**
* Your CustomStack object will be instantiated and called as such:
* CustomStack obj = new CustomStack(maxSize);
* obj.push(x);
* int param_2 = obj.pop();
* obj.increment(k,val);
*/
提交结果如下: