Finding the Shortest Unsorted Subarray with a Monotonic Stack in Go

The article explains how to locate the left and right boundaries of the unsorted segment in LeetCode 581 by using two monotonic stacks that store indices, and provides a complete Go implementation that returns the length of the shortest subarray whose sorting makes the whole array ordered.

Nullbody Notes
Nullbody Notes
Nullbody Notes
Finding the Shortest Unsorted Subarray with a Monotonic Stack in Go

LeetCode problem 581 asks for the length of the shortest continuous subarray that, when sorted, makes the whole array sorted.

The solution uses two monotonic stacks to locate the leftmost and rightmost indices of the unsorted segment. In the left‑to‑right pass the stack stores indices in increasing order; whenever a current element is smaller than the top of the stack, the index at the top is popped and the minimal popped index is recorded as the left boundary.

In the right‑to‑left pass the stack stores indices in decreasing order; when a current element is larger than the top, the top index is popped and the maximal popped index becomes the right boundary.

If no indices are popped, the array is already sorted and the answer is 0; otherwise the length is rightIndex - leftIndex + 1.

The full Go implementation is shown below, together with helper min and max functions.

func findUnsortedSubarray(nums []int) int {
    // monotonic stack
    indexStack := []int{}
    leftIndex := len(nums) - 1 // record smallest left index
    rightIndex := 0            // record largest right index

    // left to right, keep increasing order
    for i := 0; i < len(nums); i++ {
        for len(indexStack) != 0 && nums[i] < nums[indexStack[len(indexStack)-1]] {
            leftIndex = min(leftIndex, indexStack[len(indexStack)-1])
            indexStack = indexStack[:len(indexStack)-1]
        }
        indexStack = append(indexStack, i)
    }

    // right to left, keep decreasing order
    indexStack = []int{}
    for i := len(nums) - 1; i >= 0; i-- {
        for len(indexStack) != 0 && nums[i] > nums[indexStack[len(indexStack)-1]] {
            rightIndex = max(rightIndex, indexStack[len(indexStack)-1])
            indexStack = indexStack[:len(indexStack)-1]
        }
        indexStack = append(indexStack, i)
    }

    if leftIndex == len(nums)-1 && rightIndex == 0 {
        // array already sorted
        return 0
    }
    return rightIndex - leftIndex + 1
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

Repository with the solution: https://github.com/gofish2020/leetcode_forever

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

LeetCodeMonotonic Stack
Nullbody Notes
Written by

Nullbody Notes

Go backend development, learning open-source project source code together, focusing on simplicity and practicality.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.