class Solution:
def findUnsortedSubarray(self, nums):
n = len(nums)
start, end = -1, -2 # ensures 0 if already sorted
min_num, max_num = nums[-1], nums[0]
for i in range(1, n):
max_num = max(max_num, nums[i])
min_num = min(min_num, nums[n - 1 - i])
if nums[i] < max_num:
end = i
if nums[n - 1 - i] > min_num:
start = n - 1 - i
return end - start + 1
class Solution {
public:
int findUnsortedSubarray(vector<int>& nums) {
int n = nums.size();
int start = -1, end = -2;
int min_num = nums[n - 1], max_num = nums[0];
for (int i = 1; i < n; ++i) {
max_num = max(max_num, nums[i]);
min_num = min(min_num, nums[n - 1 - i]);
if (nums[i] < max_num) end = i;
if (nums[n - 1 - i] > min_num) start = n - 1 - i;
}
return end - start + 1;
}
};
class Solution {
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
int start = -1, end = -2;
int min = nums[n - 1], max = nums[0];
for (int i = 1; i < n; i++) {
max = Math.max(max, nums[i]);
min = Math.min(min, nums[n - 1 - i]);
if (nums[i] < max) end = i;
if (nums[n - 1 - i] > min) start = n - 1 - i;
}
return end - start + 1;
}
}
var findUnsortedSubarray = function(nums) {
let n = nums.length;
let start = -1, end = -2;
let min = nums[n - 1], max = nums[0];
for (let i = 1; i < n; i++) {
max = Math.max(max, nums[i]);
min = Math.min(min, nums[n - 1 - i]);
if (nums[i] < max) end = i;
if (nums[n - 1 - i] > min) start = n - 1 - i;
}
return end - start + 1;
};
Given an integer array nums
, you are to find the shortest continuous subarray (contiguous sequence of elements) that, if you sorted only this subarray in-place, the entire array would become sorted in ascending order.
0
.Constraints:
nums
of integers.At first glance, you might consider comparing the array to its sorted version to find the first and last places they differ. This would work, but sorting takes O(n log n) time and extra space.
To improve, think about what it means for a subarray to be "out of order": somewhere, elements are smaller or larger than they should be. If you could find the leftmost and rightmost positions where the order is violated, you could identify the minimal unsorted subarray.
Instead of sorting, can we scan from both ends and track the largest and smallest values seen so far? If an element is smaller than a previous max (from the left), it's out of order; if larger than a later min (from the right), it's also out of order. This leads to an efficient O(n) solution.
Here’s how the optimized algorithm works step by step:
start
and end
mark the bounds of the unsorted subarray. Initialize them so that if the array is already sorted, the result is zero.max_num
(maximum seen from the left) and min_num
(minimum seen from the right).max_num
to the maximum so far.max_num
, it's out of order; update end
to the current index.min_num
to the minimum so far.min_num
, it's out of order; update start
to the current index.end - start + 1
.end < start
and the result is zero.This approach uses only O(1) extra space and O(n) time.
Consider nums = [2, 6, 4, 8, 10, 9, 15]
.
nums[1:6]
(i.e., [6,4,8,10,9]) will sort the whole array.The optimized solution is much more efficient, especially for large arrays.
The key insight is that you don't need to sort or use extra space to find the shortest unsorted subarray. By scanning from both ends and tracking the running maximum and minimum, you can efficiently pinpoint the exact range that needs sorting. This elegant O(n) solution leverages the properties of arrays and sorting, making it both fast and space-efficient.