
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 <= 10000 <= val <= 100- At most
1000calls will be made to each method ofincrement,pushandpopeach 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
CustomStackis initialized with a maximum size,maxSize. This size prevents more thanmaxSizeelements from being added to the stack.
- The
Push Operation:
- Before adding a new element to the stack with the
pushoperation, 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
kelements of the stack by a valueval. - If
kis greater than the current size of the stack, then all elements in the stack should be incremented. - Otherwise, only the bottom
kelements 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
EnhancedStackclass is initialized with a specifiedmaxSize. It uses two vectors:dataStackto store stack elements andlazyIncrementto manage increments for each position. stackTopkeeps track of the current top index of the stack, starting from -1 indicating the stack is empty.
- The
Push Operation:
- The
pushmethod checks if there is room to add an element (i.e.,stackTopis less than the maximal index ofdataStack). If so, incrementsstackTopand assigns the new item to that position.
- The
Pop Operation:
- The
popmethod first checks if the stack is empty. If not, it computes the value atstackTopby 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
stackTopand returns the calculated value.
- The
Increment Operation:
- The
addIncrementmethod increases elements from the base of the stack up to a given count (k). It uses thelazyIncrementvector for efficient range updating by adjusting the increment at the minimal index betweenstackTopandk-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
EnhancedStackis initialized with amaxSizethat determines the capacity of the stack. - Two arrays,
elementsandincrements, are used whereelementsstores the actual stack elements andincrementsaids in the increment operation. stackTopis 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
stackTopindex 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
kelements' value by the given increment without iterating over the elements. - The
incrementsarray 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,
_elementsfor stack values and_incrementsfor holding increments applicable to elements, based on a specified sizelimit. - A
_currentIndexpointer 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
valueto the top of the stack if there is space (i.e.,_currentIndexis 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_valueto the bottomcountelements of the stack. Ifcountexceeds 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.