Next Smaller Element
#include <bits/stdc++.h> // Standard headers (iostream, vector, stack)using namespace std; // Standard namespace
// Function to find the "Next Smaller Element to the Left" for each element// The function name 'smallerElements' in context of code implies this specific problemvector<int> smallerElements(vector<int> arr, int n) { stack<int> st; // Monotonic stack to store potential smaller elements st.push(-1); // Push a sentinel value for elements with no smaller element vector<int> answer(n); // Vector to store the results (same size as input array)
// Iterate from right to left (n-1 down to 0) for(int i = n - 1; i >= 0; i--) { // While stack top is greater than or equal to current array element, pop it // This maintains a strictly increasing order from bottom to top in the stack while(st.top() >= arr[i]) { st.pop(); } // After popping, st.top() is the first element to the left that is smaller than arr[i] answer[i] = st.top(); // Store the result for arr[i] st.push(arr[i]); // Push current element onto stack as a candidate for elements further left }
return answer; // Return the result array}
int main() { vector<int> arr = {2, 3, 1}; // Example input array int n = arr.size(); // Get array size vector<int> ans = smallerElements(arr, n); // Call the function
// Print original array cout << "Original array : "; for(int i = 0; i < n; i++) { cout << arr[i] << " "; } cout << endl;
// Print the array with smaller elements found cout << "Smaller array : "; for(int i = 0; i < n; i++) { cout << ans[i] << " "; } cout << endl;
/* Dry Run: arr = {2, 3, 1}, n = 3 i = 2 (arr[2] = 1): st = [-1] while (-1 >= 1) F answer[2] = -1 st.push(1) -> st = [-1, 1]
i = 1 (arr[1] = 3): st = [-1, 1] while (1 >= 3) F answer[1] = 1 st.push(3) -> st = [-1, 1, 3]
i = 0 (arr[0] = 2): st = [-1, 1, 3] while (3 >= 2) T -> st.pop() -> st = [-1, 1] while (1 >= 2) F answer[0] = 1 st.push(2) -> st = [-1, 1, 2]
Result 'ans' = {1, 1, -1} */
return 0; // End program}
Problem
- For each element in an array, find the first element to its right (or left, depending on iteration) that is smaller than it.
- This code effectively finds the “Next Smaller Element to the Left” for each element, as it iterates from right to left. If it were iterated from left to right, it would be “Next Smaller Element to the Right”. The common naming is “Next Smaller Element” (usually implies to the right) or “Previous Smaller Element” (to the left). Given the loop
for(int i=n-1; i>=0; i--)
, this is effectively finding the Next Smaller Element to the Left.
Core Idea: Monotonic Stack
- A monotonic stack maintains elements in a particular order (e.g., increasing or decreasing).
- When looking for a “smaller” element, we maintain an increasing stack.
- Iterate from right to left (
n-1
to0
). - Stack Stores Candidates: The stack stores elements that could be the next smaller element for future (left-side) elements.
Algorithm Steps
- Initialize Stack: Push
-1
onto the stack. This acts as a default “no smaller element found” sentinel. - Iterate Right-to-Left: For each element
arr[i]
from the end to the beginning:- Pop Larger: While the
st.top()
is greater than or equal toarr[i]
,pop
from the stack. This removes elements that are no longer candidates (becausearr[i]
is smaller). - Assign Answer: The
st.top()
(after popping) is now the next smaller element to the left forarr[i]
. Store it inanswer[i]
. - Push Current:
push
arr[i]
onto the stack. It now becomes a candidate for elements further to its left.
- Pop Larger: While the