Lecture 3 (Monotonic Stack Queue Problems)¶
Next Greater Element Using Stack¶
Given an integer array A, return the next greater element for every element in A. The next greater element for an element x is the first element greater than x that we come across while traversing the array in a clockwise manner. If it doesn't exist, return -1 for this element.
Input: arr = [1, 3, 2, 4]
Output: [3, 4, 4, -1]
Input : arr = [6, 8, 0, 1, 3]
Output: [8, -1, 1, 3, -1]
Approach 1 (Brute Force)¶
- linear search with start idx
- find next greater element for every idx
In [5]:
def next_greater_element(nums):
n = len(nums)
def linear_search(start):
for i in range(start+1,n):
if nums[i] > nums[start]:
return nums[i]
return -1
result = [-1] * n
for i in range(n):
result[i] = linear_search(i)
return result
print(next_greater_element([1, 3, 2, 4]))
print(next_greater_element([6, 8, 0, 1, 3]))
[3, 4, 4, -1] [8, -1, 1, 3, -1]
Complexity Analysis¶
- N = len(nums)
O(N^2)
O(N)
Approach 2 (Using stack)¶
- backward traversal
- maintain strictly decreasing order from bottom to top
- when we encounter an element , we eleminate all the smaller elements from stack as they can never be next greater element
- stack always contains elements which are stricyly decreasing from bottom to top
- each element is pushed and popped exactly once , it gives O(N) complexity
In [ ]:
def next_greater_element(nums):
n = len(nums)
result = [-1] * n
stack = []
for i in range(n-1,-1,-1):
# eliminate all smaller elements from stack
while stack and stack[-1] <= nums[i]:
stack.pop()
result[i] = -1 if not stack else stack[-1]
stack.append(nums[i])
return result
print(next_greater_element([1, 3, 2, 4]))
print(next_greater_element([6, 8, 0, 1, 3]))
[3, 4, 4, -1] [8, -1, 1, 3, -1]
Complexity¶
- N = len(nums)
O(N)
O(N)
Next Smaller Element¶
Given an array of integers arr, your task is to find the Next Smaller Element (NSE) for every element in the array. The Next Smaller Element for an element x is defined as the first element to the right of x that is smaller than x. If there is no smaller element to the right, then the NSE is -1.
Input: arr = [4, 8, 5, 2, 25]
Output: [2, 5, 2, -1, -1]
Input: arr = [10, 9, 8, 7]
Output: [9, 8, 7, -1]
Approach 1¶
- use backward navigation
- elimnate all the elemnts from stack which are greater than the encountered element
In [14]:
def next_smaller_element(nums):
n = len(nums)
stack = []
result = [-1]* n
for i in range(n-1,-1,-1):
## eliminate all the elements from stack which are greater than encountered element
while stack and stack[-1] >= nums[i]:
stack.pop()
result[i] = -1 if not stack else stack[-1]
stack.append(nums[i])
return result
print(next_smaller_element([4, 8, 5, 2, 25]))
print(next_smaller_element([10, 9, 8, 7]))
[2, 5, 2, -1, -1] [9, 8, 7, -1]
Complexity¶
- N = len(nums)
O(N)
O(N)