Problem
Design a stack which supports the following operations.
Implement the CustomStack
class:
CustomStack(int maxSize)
Initializes the object withmaxSize
which is the maximum number of elements in the stack or do nothing if the stack reached themaxSize
.void push(int x)
Addsx
to the top of the stack if the stack hasn’t reached themaxSize
.int pop()
Pops and returns the top of stack or -1 if the stack is empty.void inc(int k, int val)
Increments the bottomk
elements of the stack byval
. If there are less thank
elements in the stack, just increment all the elements in the stack.
Example 1:
1 | Input |
Constraints:
1 <= maxSize <= 1000
1 <= x <= 1000
1 <= k <= 1000
0 <= val <= 100
- At most
1000
calls will be made to each method ofincrement
,push
andpop
each separately.
Analysis
这是一道设计题,要求设计一个可以对栈中底部k
个元素进行增加操作的栈。对于栈而言,操作栈顶的元素是容易的,但是操作栈底的元素是很麻烦的。所以第一个思路就是不直接使用栈的结构,而是用数组去实现一个栈。使用数组的好处在于可以很方便地修改栈底元素,我们把idx = 0
视为栈底,数组的右端视为栈顶,依次操作即可。分析下时间复杂度,当我们进行increment的时候,我们需要用一个while循环对前k
个元素进行修改,复杂度是$O(k)$。
上面这个方法看上去不错,但是我们有没有办法能把所有的操作的时间复杂度都做到$O(1)$呢?这里需要借助一个design类题目常用的思路——lazy operation!对于这道题来说,只有当pop
的时候我才需要知道某个元素的值,因此在inc
的时候我其实并不需要更新元素,我只需要记录一些信息,然后在pop
的时候借助这些信息计算出实际返回的值就可以了。
由于题目给出了数量的最大值,而且还是小于1000,因此我们放心地开一个数组inc
,其中inc[i]
表示从栈底到第i
个位置的increment值。当进行inc
操作时,因为对底部的k
个元素操作,所以i = k - 1
,这里还需要注意k
和栈的size的比较,两者之间取较小值,所以综合来说应该是i = min(k, st.size()) - 1
。然后我们记录inc[i] += val
,这就表示了底部的i
个元素需要增加的值。当我们pop()
获取元素的值时,计算出i = st.size() - 1
,然后到inc[i]
中找到需要增加的值加到元素本身就可以了。这里还要注意,因为我们需要对底部剩下的元素生效,所以应该有一个累加的操作,即inc[i - 1] += inc[i]
,这样就把增加的值传递到之前的元素了。
Solution
无。
Code
方法1:
1 | class CustomStack { |
方法2:
1 | class CustomStack { |
Summary
这道题目很容易想到用方法1解决,也能通过OJ,但是更好的处理应该是使用方法2。方法2的懒加载体现了design类型题目的特点,通过记录变更信息,最后再计算实际结果。这道题目的分享到这里,感谢你的支持!