Minimum Window Sort
Mahabharata — Drona Arranges the Army — Finding the Disordered Regiment
सैन्यस्य मध्ये यत् भ्रष्टं क्रमं तत् साधु निर्णयेत्। वामाद् दक्षिणतः दृष्ट्वा न्यूनं खण्डं विनिश्चयेत्॥
*In the midst of the army, discern what has broken formation. Looking from left and right, determine the minimum flawed section.*
The Story
The fourteenth day of the Kurukshetra war had broken all order. Drona, supreme commander of the Kaurava forces, surveyed the battlefield at dawn with a general's calculating eye. Hundreds of regiments had fought through the night; some had held their formation, others had scattered and reformed haphazardly.
"The regiments are numbered by their strength," Drona told his charioteer. "Regiment 1 is weakest, regiment N is strongest. For maximum battle effectiveness, they must stand in order from weakest to strongest, left to right across the field. But last night's chaos has disordered some of them."
He unrolled the troop roster and read the current positions aloud: [2, 6, 4, 8, 10, 9, 15]
"Most are correctly placed. I need to find the shortest contiguous section I must rearrange to restore complete order."
Karna, standing nearby, made the warrior's instinctive suggestion: "Lord Drona, simply sort the entire array. It is certainly correct then."
"And disrupt the regiments already in correct formation? Foolish and costly," Drona replied. "I need the minimum window — the smallest subarray that, if sorted, makes the whole array sorted."
Ashwatthama, Drona's son, tried another approach: "Father, we could try every possible subarray, sort each one, and check if the whole array is sorted. The smallest valid subarray is our answer."
"That is O(n³) operations," Drona said patiently. "For a thousand regiments, unacceptable."
Drona closed his eyes. He thought about what it meant for a section to be disordered. A regiment is *out of place* if it is smaller than what comes after it (from the right perspective) or larger than what comes before it (from the left perspective).
"Two observations," Drona announced. "First: scan left to right, tracking the running maximum. Any regiment that is *smaller* than the maximum seen so far is disordered. The *rightmost* such regiment marks the right boundary of our window."
He moved his finger along the roster: max=2, max=6, max=6 but arr[2]=4 < 6! Disordered. max=8, max=10, max=10 but arr[5]=9 < 10! Disordered. max=15.
"The rightmost disorder is at index 5, value 9. That is our right boundary."
"Second: scan right to left, tracking the running minimum. Any regiment that is *larger* than the minimum seen so far is disordered. The *leftmost* such regiment marks the left boundary."
He scanned from the right: min=15, min=9, min=9 but arr[4]=10 > 9! Disordered. min=8, min=8 but arr[2]=4... wait, arr[1]=6 > 4. Disordered. min=4, min=4 but arr[0]=2 is fine (2 < 4). Actually let's recheck: scanning right-to-left: min=15, 9<15→min=9, 10>9→disordered at index 4. Continue: min=9 still. 8<9→min=8. 4<8→min=4. 6>4→disordered at index 1. 2<4→fine.
"The leftmost disorder is at index 1, value 6. That is our left boundary."
"So I only need to rearrange regiments at indices 1 through 5 — the subarray [6, 4, 8, 10, 9]," Drona concluded. "If I sort just that section, the entire array becomes [2, 4, 6, 8, 9, 10, 15] — perfectly ordered."
Ashwatthama verified: 2 ≤ 4 ≤ 6 ≤ 8 ≤ 9 ≤ 10 ≤ 15. Perfect.
"The length of the minimum window is right - left + 1 = 5 - 1 + 1 = 5."
Karna, grudgingly impressed, asked: "But what if the array is already perfectly sorted?"
"Then no element is ever smaller than the running maximum going left-to-right, and no element is ever larger than the running minimum going right-to-left. Both left and right remain at their sentinel values of -1. I return 0 — zero regiments need rearranging."
Drona dispatched his orders. Five regiments were repositioned. The Kaurava left flank snapped back into lethal formation just as the Pandava conches blared the morning charge.
"The minimum intervention yields the maximum result," Drona murmured, picking up his bow.
This is the Two Pointer technique for finding the minimum window sort.
Ashwatthama's First Instinct
Try every possible subarray [i, j]. For each, check if sorting that subarray makes the whole array sorted. Return the shortest valid subarray length. O(n³) time.
public int findUnsortedSubarrayBruteForce(int[] nums) {
int n = nums.length;
int minLen = 0; // 0 means already sorted
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// Sort nums[i..j] in a copy and check if whole array becomes sorted
int[] copy = nums.clone();
Arrays.sort(copy, i, j + 1);
boolean sorted = true;
for (int k = 1; k < n; k++) {
if (copy[k] < copy[k-1]) { sorted = false; break; }
}
if (sorted) {
minLen = Math.max(minLen, j - i + 1); // track for correctness
// Actually want minimum, so:
}
}
}
// Proper minimum-finding logic omitted for brevity, O(n^3) total
return minLen;
}Drona's Wisdom
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
int left = -1, right = -1;
int runningMax = Integer.MIN_VALUE;
int runningMin = Integer.MAX_VALUE;
// Pass 1: left → right, find rightmost out-of-order element
for (int i = 0; i < n; i++) {
runningMax = Math.max(runningMax, nums[i]);
// This element is smaller than something to its left
if (nums[i] < runningMax) {
right = i; // Keep updating — we want the rightmost
}
}
// Array is already sorted
if (right == -1) return 0;
// Pass 2: right → left, find leftmost out-of-order element
for (int i = n - 1; i >= 0; i--) {
runningMin = Math.min(runningMin, nums[i]);
// This element is larger than something to its right
if (nums[i] > runningMin) {
left = i; // Keep updating — we want the leftmost
}
}
return right - left + 1;
}
// Test with Drona's regiment formation
public static void main(String[] args) {
int[] regiments = {2, 6, 4, 8, 10, 9, 15};
System.out.println(new Solution().findUnsortedSubarray(regiments));
// Output: 5 (indices 1-5: [6,4,8,10,9] must be sorted)
}Step-by-Step Walkthrough
Array: [2, 6, 4, 8, 10, 9, 15] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PASS 1 — Left to Right (find right boundary) i=0: runMax=2, nums[0]=2 ≥ 2 → OK i=1: runMax=6, nums[1]=6 ≥ 6 → OK i=2: runMax=6, nums[2]=4 < 6 → right=2 i=3: runMax=8, nums[3]=8 ≥ 8 → OK i=4: runMax=10, nums[4]=10 ≥ 10 → OK i=5: runMax=10, nums[5]=9 < 10 → right=5 ← final i=6: runMax=15, nums[6]=15 ≥ 15 → OK Right boundary = 5 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PASS 2 — Right to Left (find left boundary) i=6: runMin=15, nums[6]=15 ≤ 15 → OK i=5: runMin=9, nums[5]=9 ≤ 9 → OK i=4: runMin=9, nums[4]=10 > 9 → left=4 i=3: runMin=8, nums[3]=8 ≤ 8 → OK i=2: runMin=4, nums[2]=4 ≤ 4 → OK i=1: runMin=4, nums[1]=6 > 4 → left=1 ← final i=0: runMin=2, nums[0]=2 ≤ 4 → OK Left boundary = 1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ✅ Window = [1, 5] = [6, 4, 8, 10, 9] Length = 5 - 1 + 1 = 5 Verify: sorted window → [4, 6, 8, 9, 10] Full array: [2, 4, 6, 8, 9, 10, 15] ✓ sorted
Deep Insight
**Why does tracking runningMax give the right boundary?**
If `nums[i] < runningMax`, it means `nums[i]` is smaller than some element to its left. After sorting the window, `nums[i]` must move left — it's out of place. The rightmost such element is the furthest right we must sort.
**Why does tracking runningMin give the left boundary?**
If `nums[i] > runningMin` (scanning right-to-left), it means `nums[i]` is larger than some element to its right. After sorting, `nums[i]` must move right — it's out of place. The leftmost such element is the furthest left we must sort.
**Edge cases:** - Already sorted: `right` never updates from -1, return 0 - Fully reversed: `left=0, right=n-1`, return n - Single element: trivially sorted, return 0 - Two elements: single comparison determines 0 or 2
**Why O(1) space?** Only two integers (`left`, `right`) and two running trackers. No auxiliary array needed.
Complexity Analysis
| Approach | Time | Space | Note |
|---|---|---|---|
| Brute Force | O(n³) | O(n) | O(n²) subarrays × O(n) sort + check per subarray |
| Optimal | O(n) | O(1) | Two linear passes, only constant extra space |
Pattern Recognition
✅ Array that is mostly sorted with a disordered middle section ✅ Find minimum subarray to sort to make whole array sorted ✅ Two separate scans (L→R and R→L) each tracking an extreme ✅ No explicit sorting needed in the final solution **LeetCode Trigger Phrases:** → "shortest subarray... if you sort it... whole array is sorted" → "minimum length subarray... out of order" → "find the unsorted continuous subarray"
Bhagavad Gita 3.21
यद्यदाचरति श्रेष्ठस्तत्तदेवेतरो जनः। स यत्प्रमाणं कुरुते लोकस्तदनुवर्तते॥
Whatever a great person does, others follow. Whatever standard they set, the world follows that.
Connection: The algorithm finds the minimum disruption that, once corrected, restores order to the whole. Like a great commander (Drona) who identifies the exact regiment out of formation — not more, not less — the wise solution touches only what is truly disordered. The running maximum and minimum are the 'standards' of the sorted order; any element violating these standards reveals the window that must be set right.