Given an integer array nums
, you need to find one continuous subarray such that if you only sort this subarray in non-decreasing order, then the whole array will be sorted in non-decreasing 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^4
-10^5 <= nums[i] <= 10^5
Can you solve it in O(n) time complexity?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The problem asks us to find the smallest section of a list that, if sorted, would make the whole list sorted. The brute force way is to simply check every possible section of the list.
Here's how the algorithm would work step-by-step:
def find_unsorted_subarray_brute_force(numbers):
list_length = len(numbers)
shortest_unsorted_length = list_length
start_index_result = -1
end_index_result = -1
for start_index in range(list_length):
for end_index in range(start_index, list_length):
# Create a copy to avoid modifying the original list
temp_numbers = numbers[:]
# Sort the subarray from start_index to end_index
subarray_to_sort = temp_numbers[start_index:end_index+1]
subarray_to_sort.sort()
temp_numbers[start_index:end_index+1] = subarray_to_sort
is_sorted = True
for index in range(list_length - 1):
if temp_numbers[index] > temp_numbers[index + 1]:
is_sorted = False
break
if is_sorted:
#Check if the current subarray is shorter than the existing one.
current_length = end_index - start_index + 1
if current_length < shortest_unsorted_length:
shortest_unsorted_length = current_length
start_index_result = start_index
end_index_result = end_index
#If the entire array was already sorted.
if start_index_result == -1:
return 0
else:
return shortest_unsorted_length
The trick to finding the shortest unsorted section is to realize a sorted array has numbers increasing from left to right. Therefore, we aim to find the first instance where this order breaks from the left and the right, which marks the boundaries of our unsorted section.
Here's how the algorithm would work step-by-step:
def shortest_unsorted_continuous_subarray(nums):
array_length = len(nums)
start_index = -1
end_index = -1
# Find the potential start of the unsorted subarray.
for i in range(array_length - 1):
if nums[i] > nums[i + 1]:
start_index = i
break
# If the array is sorted, return 0.
if start_index == -1:
return 0
# Find the potential end of the unsorted subarray.
for i in range(array_length - 1, 0, -1):
if nums[i] < nums[i - 1]:
end_index = i
break
# Find the minimum and maximum values within the unsorted subarray.
subarray_maximum = max(nums[start_index:end_index + 1])
subarray_minimum = min(nums[start_index:end_index + 1])
# Extend the unsorted subarray to the left if needed.
for i in range(start_index + 1):
if nums[i] > subarray_minimum:
start_index = i
break
# Extend the unsorted subarray to the right if needed.
for i in range(array_length - 1, end_index - 1, -1):
if nums[i] < subarray_maximum:
end_index = i
break
# Calculate the length of the unsorted subarray.
return end_index - start_index + 1
Case | How to Handle |
---|---|
Empty input array | Return 0 immediately since no subarray needs sorting. |
Already sorted array | The algorithm should identify this and return 0. |
Array with only two elements, sorted or unsorted | Should correctly identify if a swap is needed and return 2 or 0 accordingly. |
Array with all identical elements | Should correctly return 0 as no sorting is required. |
Array sorted in descending order | Should return the full array length as the entire array needs sorting. |
Array with a small unsorted section at the beginning | The algorithm should correctly identify the start and end of the unsorted subarray. |
Array with a small unsorted section at the end | The algorithm should correctly identify the start and end of the unsorted subarray. |
Array with duplicate values within the unsorted subarray | The algorithm should still correctly identify the boundaries of the minimal unsorted subarray containing these duplicates. |