Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
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.
Example 1:
Input: 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.
Example 2:
Input: nums = [1,2,3,4,3] Output: [2,3,4,-1,4]
Constraints:
1 <= nums.length <= 104-109 <= nums[i] <= 109Problem summary: 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Stack
[1,2,1]
[1,2,3,4,3]
next-greater-element-i)next-greater-element-iii)maximum-and-minimum-sums-of-at-most-size-k-subarrays)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #503: Next Greater Element II
class Solution {
public int[] nextGreaterElements(int[] nums) {
int n = nums.length;
int[] ans = new int[n];
Arrays.fill(ans, -1);
Deque<Integer> stk = new ArrayDeque<>();
for (int i = n * 2 - 1; i >= 0; --i) {
int j = i % n;
while (!stk.isEmpty() && stk.peek() <= nums[j]) {
stk.pop();
}
if (!stk.isEmpty()) {
ans[j] = stk.peek();
}
stk.push(nums[j]);
}
return ans;
}
}
// Accepted solution for LeetCode #503: Next Greater Element II
func nextGreaterElements(nums []int) []int {
n := len(nums)
ans := make([]int, n)
for i := range ans {
ans[i] = -1
}
stk := []int{}
for i := n*2 - 1; i >= 0; i-- {
j := i % n
for len(stk) > 0 && stk[len(stk)-1] <= nums[j] {
stk = stk[:len(stk)-1]
}
if len(stk) > 0 {
ans[j] = stk[len(stk)-1]
}
stk = append(stk, nums[j])
}
return ans
}
# Accepted solution for LeetCode #503: Next Greater Element II
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [-1] * n
stk = []
for i in range(n * 2 - 1, -1, -1):
i %= n
while stk and stk[-1] <= nums[i]:
stk.pop()
if stk:
ans[i] = stk[-1]
stk.append(nums[i])
return ans
// Accepted solution for LeetCode #503: Next Greater Element II
struct Solution;
impl Solution {
fn next_greater_elements(nums: Vec<i32>) -> Vec<i32> {
let mut stack: Vec<usize> = vec![];
let n = nums.len();
let mut res = vec![-1; n];
for i in 0..2 * n {
let j = i % n;
let x = nums[j];
while let Some(top) = stack.pop() {
if nums[top] < x {
res[top] = x;
} else {
stack.push(top);
break;
}
}
stack.push(j);
}
res
}
}
#[test]
fn test() {
let nums = vec![1, 2, 1];
let res = vec![2, -1, 2];
assert_eq!(Solution::next_greater_elements(nums), res);
}
// Accepted solution for LeetCode #503: Next Greater Element II
function nextGreaterElements(nums: number[]): number[] {
const n = nums.length;
const stk: number[] = [];
const ans: number[] = Array(n).fill(-1);
for (let i = n * 2 - 1; ~i; --i) {
const j = i % n;
while (stk.length && stk.at(-1)! <= nums[j]) {
stk.pop();
}
if (stk.length) {
ans[j] = stk.at(-1)!;
}
stk.push(nums[j]);
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
For each element, scan left (or right) to find the next greater/smaller element. The inner scan can visit up to n elements per outer iteration, giving O(n²) total comparisons. No extra space needed beyond loop variables.
Each element is pushed onto the stack at most once and popped at most once, giving 2n total operations = O(n). The stack itself holds at most n elements in the worst case. The key insight: amortized O(1) per element despite the inner while-loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Pushing without popping stale elements invalidates next-greater/next-smaller logic.
Usually fails on: Indices point to blocked elements and outputs shift.
Fix: Pop while invariant is violated before pushing current element.