Next Greater Element II

July 12, 2025

Question

Given a circular array, for each element, find the next greater number. The next greater number is the first number you encounter going forward (looping back if needed) that is bigger than the current one.

If it doesn't exist, return -1 for that element.

Example

Input: [1, 2, 3, 2, 1]

Output: [2, 3, -1, 3, 2]

Explanation: Starting at each index, look ahead (including wrapping around) to find the first bigger number.

My Notes 📝

📌 Summary Rule of Thumb

  • ❓ Is my key a simple integer index from 0 to n-1?
    ✅ Use a slice.
  • ❓ Is my key more complex (e.g., string, timestamp, sparse ID)?
    ✅ Use a map.

💻 Solution 1: Using Result Array

package main

import (
    "fmt"
)

type Stack struct {
    items []int
}

func (s *Stack) Push(item int) {
    s.items = append(s.items, item)
}

func (s *Stack) Pop() int {
    popped := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return popped
}

func (s *Stack) Top() int {
    return s.items[len(s.items)-1]
}

func (s *Stack) Empty() bool {
    return len(s.items) == 0
}

func nextGreaterElements(nums []int) []int {
    stack := Stack{}
    n := len(nums)
    answer := make([]int, n)
    for i := range answer {
        answer[i] = -1
    }

    for i := 0; i < 2*n; i++ {
        val := nums[i % n]
        for !stack.Empty() && nums[stack.Top()] < val {
            index := stack.Pop()
            answer[index] = val
        }
        if i < n {
            stack.Push(i)
        }
    }

    return answer
}

func main() {
    result := nextGreaterElements([]int{1, 2, 3, 2, 1})
    fmt.Println(result)
}

💡 Solution 2: Using Map

package main

import (
    "fmt"
)

type Stack struct {
    items []int
}

func (s *Stack) Push(item int) {
    s.items = append(s.items, item)
}

func (s *Stack) Pop() int {
    popped := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return popped
}

func (s *Stack) Top() int {
    return s.items[len(s.items)-1]
}

func (s *Stack) Empty() bool {
    return len(s.items) == 0
}

func nextGreaterElements(nums []int) []int {
    stack := Stack{}
    lookup := make(map[int]int)
    n := len(nums)

    for i := 0; i < 2*n; i++ {
        val := nums[i % n]
        for !stack.Empty() && nums[stack.Top()] < val {
            index := stack.Pop()
            lookup[index] = val
        }
        if i < n {
            stack.Push(i)
        }
    }

    for i := range nums {
        if val, ok := lookup[i]; ok {
            nums[i] = val
        } else {
            nums[i] = -1
        }
    }

    return nums
}

func main() {
    result := nextGreaterElements([]int{1, 2, 3, 2, 1})
    fmt.Println(result)
}