Given a circular integer array nums
(i.e., the next element of nums[nums.length - 1]
is nums[0]
), return the next greater number for every element in nums
. The next greater number of a number x
is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn't exist, return -1
for this number.
For example:
nums = [1,2,1]
Output: [2,-1,2]
Explanation: The first 1's next greater number is 2; The number 2 can't find next greater number. The second 1's next greater number needs to search circularly, which is also 2.
As another example:
nums = [1,2,3,4,3]
Output: [2,3,4,-1,4]
## Next Greater Element II
This problem requires us to find the next greater element for each element in a circular array. We can use a stack to efficiently keep track of potential next greater elements as we iterate through the array (potentially multiple times to simulate circularity).
### 1. Brute Force Solution
A naive approach would be to iterate through the array for each element and search for the next greater element in a circular fashion.
```python
def nextGreaterElements_brute_force(nums):
n = len(nums)
result = [-1] * n
for i in range(n):
for j in range(1, n): # Start from the next element
if nums[(i + j) % n] > nums[i]:
result[i] = nums[(i + j) % n]
break
return result
Explanation:
i
, we iterate through the rest of the array (virtually circular) using the modulo operator (i + j) % n
.nums[i]
, we update result[i]
and break the inner loop.result[i]
remains -1
.We can improve upon the brute force approach by using a stack to store indices of elements for which we are looking for the next greater element. This allows us to find the next greater element in O(n) time.
def nextGreaterElements(nums):
n = len(nums)
result = [-1] * n
stack = [] # Stack to store indices
for i in range(2 * n): # Iterate twice to simulate circular array
num = nums[i % n] # Actual element from array
while stack and nums[stack[-1]] < num:
index = stack.pop()
result[index] = num
if i < n: # Only push indices from the original array
stack.append(i)
return result
Explanation:
2 * n
) to simulate the circular nature. The modulo operator (i % n
) helps access elements circularly.stack
stores indices of elements for which we haven't found the next greater element yet.num
is greater than the element at the top of the stack (nums[stack[-1]]
), it means we've found the next greater element for the element at the top of the stack. We pop the index from the stack and update the result
array.2n
times. While the while
loop looks like it might add to the complexity, each element is pushed onto the stack at most once and popped at most once. Thus, the amortized time complexity for the while
loop is O(n). Therefore, the total time complexity is O(2n) which simplifies to O(n).n
times, and the inner loop runs up to n
times in the worst case, resulting in O(n*n) = O(n^2) complexity.result
array stores n
elements. The stack, in the worst-case scenario (decreasing array), can hold up to n
indices. Therefore the space complexity is O(n + n) = O(n).result
array stores n
elements. Therefore the space complexity is O(n).nums
is empty, the function should return an empty array.Example Edge Cases:
nums = []
returns []
nums = [5, 5, 5]
returns [-1, -1, -1]
nums = [5, 4, 3, 2, 1]
returns [-1, -1, -1, -1, -1]
nums = [5, 1, 2, 3, 4]
returns [-1, 2, 3, 4, 5]