
Problem Statement
In this problem, you are required to design a special kind of stack called CustomStack
that not only performs the usual push and pop operations but can also increment a specified number of elements starting from the bottom of the stack. The CustomStack
allows for the initialization with a maximum size, providing a limit to the number of elements it can hold. Elements are added to the top unless the stack has reached its maximum capacity. The pop operation will remove the top element and return its value or return -1
if the stack is empty. Additionally, the increment operation is required to increase the value of the bottom k
elements by a given value val
. If the stack contains fewer than k
elements, then all elements will be incremented.
Examples
Example 1
Input:
["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]
Explanation:
CustomStack stk = new CustomStack(3); // Stack is Empty [] stk.push(1); // stack becomes [1] stk.push(2); // stack becomes [1, 2] stk.pop(); // return 2 --> Return top of the stack 2, stack becomes [1] stk.push(2); // stack becomes [1, 2] stk.push(3); // stack becomes [1, 2, 3] stk.push(4); // stack still [1, 2, 3], Do not add another elements as size is 4 stk.increment(5, 100); // stack becomes [101, 102, 103] stk.increment(2, 100); // stack becomes [201, 202, 103] stk.pop(); // return 103 --> Return top of the stack 103, stack becomes [201, 202] stk.pop(); // return 202 --> Return top of the stack 202, stack becomes [201] stk.pop(); // return 201 --> Return top of the stack 201, stack becomes [] stk.pop(); // return -1 --> Stack is empty return -1.
Constraints
1 <= maxSize, x, k <= 1000
0 <= val <= 100
- At most
1000
calls will be made to each method ofincrement
,push
andpop
each separately.
Approach and Intuition
The problem requires a stack with enhanced functionality. Here's a step-by-step breakdown of how the operations are handled:
Initialization:
- The
CustomStack
is initialized with a maximum size,maxSize
. This size prevents more thanmaxSize
elements from being added to the stack.
- The
Push Operation:
- Before adding a new element to the stack with the
push
operation, check if the current size of the stack is less thanmaxSize
. - If true, add the element to the top of the stack.
- Before adding a new element to the stack with the
Pop Operation:
- Check if the stack is not empty before popping.
- If the stack is empty, return
-1
. - If not, remove the top element from the stack and return its value.
Increment Operation:
- This operation adds more complexity. It requires incrementing the bottom
k
elements of the stack by a valueval
. - If
k
is greater than the current size of the stack, then all elements in the stack should be incremented. - Otherwise, only the bottom
k
elements are incremented.
- This operation adds more complexity. It requires incrementing the bottom
By understanding these operations, we can maintain the stacking order and ensure the additional increment functionality does not disrupt the primary operations of push and pop. The design ensures efficiency and simplicity, keeping track of current size and applying increments directly to elements in the stack without additional structures. This approach also considers performance constraints, ensuring that each operation can handle up to 1000 calls efficiently.
Solutions
- C++
- Java
- Python
class EnhancedStack {
private:
vector<int> dataStack;
vector<int> lazyIncrement;
int stackTop;
public:
EnhancedStack(int maxSize) {
dataStack.resize(maxSize);
lazyIncrement.resize(maxSize);
stackTop = -1;
}
void push(int x) {
if (stackTop < (int)(dataStack.size()) - 1) {
dataStack[++stackTop] = x;
}
}
int pop() {
if (stackTop == -1) {
return -1;
}
int value = dataStack[stackTop] + lazyIncrement[stackTop];
if (stackTop > 0) {
lazyIncrement[stackTop - 1] += lazyIncrement[stackTop];
}
lazyIncrement[stackTop] = 0;
stackTop--;
return value;
}
void addIncrement(int k, int val) {
if (stackTop >= 0) {
int limit = min(stackTop, k - 1);
lazyIncrement[limit] += val;
}
}
};
For the given problem title "Design a Stack With Increment Operation", the C++ code implements an enhanced stack capable of not only standard push and pop operations but also a custom "increment" operation to efficiently increase the bottommost elements of the stack.
Initialization:
- The
EnhancedStack
class is initialized with a specifiedmaxSize
. It uses two vectors:dataStack
to store stack elements andlazyIncrement
to manage increments for each position. stackTop
keeps track of the current top index of the stack, starting from -1 indicating the stack is empty.
- The
Push Operation:
- The
push
method checks if there is room to add an element (i.e.,stackTop
is less than the maximal index ofdataStack
). If so, incrementsstackTop
and assigns the new item to that position.
- The
Pop Operation:
- The
pop
method first checks if the stack is empty. If not, it computes the value atstackTop
by combining the base stack value and the increment stored at the same index. - Before decrementing
stackTop
, it propagates the increment value to the next element in the stack (if present). This lazy propagation ensures that only necessary computations occur, thereby enhancing efficiency. - Resets the increment at
stackTop
and returns the calculated value.
- The
Increment Operation:
- The
addIncrement
method increases elements from the base of the stack up to a given count (k
). It uses thelazyIncrement
vector for efficient range updating by adjusting the increment at the minimal index betweenstackTop
andk-1
.
- The
This intelligently designed class efficiently manages increments to collections of elements at the stack's bottom with minimal computations, making the stack operations highly optimized for scenarios where frequent increment adjustments are needed alongside regular pushes and pops.
class EnhancedStack {
private int[] elements;
private int[] increments;
private int stackTop;
public EnhancedStack(int maxSize) {
elements = new int[maxSize];
increments = new int[maxSize];
stackTop = -1;
}
public void push(int value) {
if (stackTop < elements.length - 1) {
elements[++stackTop] = value;
}
}
public int pop() {
if (stackTop < 0) {
return -1;
}
int poppedValue = elements[stackTop] + increments[stackTop];
if (stackTop > 0) {
increments[stackTop - 1] += increments[stackTop];
}
increments[stackTop] = 0;
stackTop--;
return poppedValue;
}
public void increment(int k, int value) {
if (stackTop >= 0) {
int maxIncrementIndex = Math.min(stackTop, k - 1);
increments[maxIncrementIndex] += value;
}
}
}
The given Java code defines an EnhancedStack
class designed to implement a stack with an additional increment operation. This feature-rich stack allows standard functionality like push and pop operations, along with the ability to increment the bottom k
elements of the stack by a specified value in a single operation.
Functionality Breakdown:
Initialization:
- The
EnhancedStack
is initialized with amaxSize
that determines the capacity of the stack. - Two arrays,
elements
andincrements
, are used whereelements
stores the actual stack elements andincrements
aids in the increment operation. stackTop
is an index tracking the top element of the stack.
- The
Push Operation:
- Adds a new element to the top of the stack if there's available space.
- Increases the
stackTop
index accordingly.
Pop Operation:
- Returns and removes the top element of the stack.
- Applies any accrued increments to the popped element.
- Propagates this increment to the next element if the stack isn't empty after the pop, ensuring any subsequent pops consider earlier increments.
Increment Operation:
- Efficiently increases the bottom
k
elements' value by the given increment without iterating over the elements. - The
increments
array tracks increments at relevant positions, utilizing the propagation method during pops to apply these increments.
- Efficiently increases the bottom
This implementation ensures all operations (push, pop, and increment) are efficiently handled, making it suitable for scenarios requiring swift stack manipulations with additional complex operations like the bottom element increments. The use of an increments
array for deferred increment application optimizes the increment operation, especially for large stacks.
class StackContainer:
def __init__(self, limit: int):
self._elements = [0] * limit
self._increments = [0] * limit
self._currentIndex = -1
def push(self, value: int) -> None:
if self._currentIndex < len(self._elements) - 1:
self._currentIndex += 1
self._elements[self._currentIndex] = value
def pop(self) -> int:
if self._currentIndex == -1:
return -1
top_value = self._elements[self._currentIndex] + self._increments[self._currentIndex]
if self._currentIndex != 0:
self._increments[self._currentIndex - 1] += self._increments[self._currentIndex]
self._increments[self._currentIndex] = 0
self._currentIndex -= 1
return top_value
def increment(self, count: int, increment_value: int) -> None:
if self._currentIndex >= 0:
position = min(self._currentIndex, count - 1)
self._increments[position] += increment_value
This Python solution describes the implementation of a custom stack class StackContainer
with the capability to support normal stack operations and an additional increment operation. The class manages stack operations with the following methods:
__init__(self, limit: int)
:- Initializes the stack with two arrays,
_elements
for stack values and_increments
for holding increments applicable to elements, based on a specified sizelimit
. - A
_currentIndex
pointer is used to track the top element of the stack.
- Initializes the stack with two arrays,
push(self, value: int) -> None
:- Adds a new element
value
to the top of the stack if there is space (i.e.,_currentIndex
is less than the top boundary of the stack).
- Adds a new element
pop(self) -> int
:- Removes the top element from the stack and returns its value, including any increments.
- Adjusts the increment values so that the next top element, if available, receives the accumulated increments from the popped element.
increment(self, count: int, increment_value: int) -> None
:- Applies an
increment_value
to the bottomcount
elements of the stack. Ifcount
exceeds the number of elements in the stack, the increment is applied up to the last element.
- Applies an
This implementation efficiently handles the increment operation in a way that does not require iterating over all elements every time an increment is applied; instead, it strategically updates increment values, adding computational efficiency in scenarios where there are frequent increment operations.
No comments yet.