581. Shortest Unsorted Continuous Subarray
Problem Description
Given an integer array nums, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order.
Return the shortest such subarray and output its length.
Example 1:
Input: nums = [2,6,4,8,10,9,15]
Output: 5
Explanation: You need to sort [6,4,8,10,9] in ascending order to make the whole array sorted in ascending order.
Example 2:
Input: nums = [1,2,3,4]
Output: 0
Example 3:
Input: nums = [1]
Output: 0
Constraints:
1 <= nums.length <= 10⁴-10⁵ <= nums[i] <= 10⁵
Solution
Python Solution
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
n = len(nums)
if n < 2:
return 0
# Find the first number out of order from left
left = 0
while left < n - 1 and nums[left] <= nums[left + 1]:
left += 1
if left == n - 1: # Array is already sorted
return 0
# Find the first number out of order from right
right = n - 1
while right > 0 and nums[right] >= nums[right - 1]:
right -= 1
# Find min and max in the middle subarray
min_val = min(nums[left:right + 1])
max_val = max(nums[left:right + 1])
# Extend left boundary
while left > 0 and nums[left - 1] > min_val:
left -= 1
# Extend right boundary
while right < n - 1 and nums[right + 1] < max_val:
right += 1
return right - left + 1
Time Complexity: O(n)
Where n is the length of the input array. We traverse the array a constant number of times.
Space Complexity: O(1)
We only use a constant amount of extra space.
Java Solution
class Solution {
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
if (n < 2) {
return 0;
}
// Find the first number out of order from left
int left = 0;
while (left < n - 1 && nums[left] <= nums[left + 1]) {
left++;
}
if (left == n - 1) { // Array is already sorted
return 0;
}
// Find the first number out of order from right
int right = n - 1;
while (right > 0 && nums[right] >= nums[right - 1]) {
right--;
}
// Find min and max in the middle subarray
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = left; i <= right; i++) {
min = Math.min(min, nums[i]);
max = Math.max(max, nums[i]);
}
// Extend left boundary
while (left > 0 && nums[left - 1] > min) {
left--;
}
// Extend right boundary
while (right < n - 1 && nums[right + 1] < max) {
right++;
}
return right - left + 1;
}
}
Time Complexity: O(n)
Where n is the length of the input array. We traverse the array a constant number of times.
Space Complexity: O(1)
We only use a constant amount of extra space.
C++ Solution
class Solution {
public:
int findUnsortedSubarray(vector& nums) {
int n = nums.size();
if (n < 2) {
return 0;
}
// Find the first number out of order from left
int left = 0;
while (left < n - 1 && nums[left] <= nums[left + 1]) {
left++;
}
if (left == n - 1) { // Array is already sorted
return 0;
}
// Find the first number out of order from right
int right = n - 1;
while (right > 0 && nums[right] >= nums[right - 1]) {
right--;
}
// Find min and max in the middle subarray
int min_val = INT_MAX;
int max_val = INT_MIN;
for (int i = left; i <= right; i++) {
min_val = min(min_val, nums[i]);
max_val = max(max_val, nums[i]);
}
// Extend left boundary
while (left > 0 && nums[left - 1] > min_val) {
left--;
}
// Extend right boundary
while (right < n - 1 && nums[right + 1] < max_val) {
right++;
}
return right - left + 1;
}
};
Time Complexity: O(n)
Where n is the length of the input array. We traverse the array a constant number of times.
Space Complexity: O(1)
We only use a constant amount of extra space.
JavaScript Solution
/**
* @param {number[]} nums
* @return {number}
*/
var findUnsortedSubarray = function(nums) {
const n = nums.length;
if (n < 2) {
return 0;
}
// Find the first number out of order from left
let left = 0;
while (left < n - 1 && nums[left] <= nums[left + 1]) {
left++;
}
if (left === n - 1) { // Array is already sorted
return 0;
}
// Find the first number out of order from right
let right = n - 1;
while (right > 0 && nums[right] >= nums[right - 1]) {
right--;
}
// Find min and max in the middle subarray
let min = Math.min(...nums.slice(left, right + 1));
let max = Math.max(...nums.slice(left, right + 1));
// Extend left boundary
while (left > 0 && nums[left - 1] > min) {
left--;
}
// Extend right boundary
while (right < n - 1 && nums[right + 1] < max) {
right++;
}
return right - left + 1;
};
Time Complexity: O(n)
Where n is the length of the input array. We traverse the array a constant number of times.
Space Complexity: O(1)
We only use a constant amount of extra space.
C# Solution
public class Solution {
public int FindUnsortedSubarray(int[] nums) {
int n = nums.Length;
if (n < 2) {
return 0;
}
// Find the first number out of order from left
int left = 0;
while (left < n - 1 && nums[left] <= nums[left + 1]) {
left++;
}
if (left == n - 1) { // Array is already sorted
return 0;
}
// Find the first number out of order from right
int right = n - 1;
while (right > 0 && nums[right] >= nums[right - 1]) {
right--;
}
// Find min and max in the middle subarray
int min = int.MaxValue;
int max = int.MinValue;
for (int i = left; i <= right; i++) {
min = Math.Min(min, nums[i]);
max = Math.Max(max, nums[i]);
}
// Extend left boundary
while (left > 0 && nums[left - 1] > min) {
left--;
}
// Extend right boundary
while (right < n - 1 && nums[right + 1] < max) {
right++;
}
return right - left + 1;
}
}
Time Complexity: O(n)
Where n is the length of the input array. We traverse the array a constant number of times.
Space Complexity: O(1)
We only use a constant amount of extra space.
Approach Explanation
The solution uses a two-pointer approach with min-max tracking:
- Key Insights:
- Two-pointer technique
- Min-max tracking
- Boundary extension
- Order violation
- Algorithm Steps:
- Find boundaries
- Track min-max
- Extend range
- Calculate length
Implementation Details:
- Boundary checking
- Order comparison
- Range extension
- Length calculation
Optimization Insights:
- Early termination
- Single pass
- Space efficiency
- Boundary handling
Edge Cases:
- Already sorted
- Single element
- All equal
- Reverse sorted