E-581. Shortest Unsorted Continuous Subarray
# 2: O(n), O(1)
'''
观察一下subarray和整体array的关系.
在未排序的subarray的部分, 我们知道这个subarray里面的最大值要比排序部分的右半部分最小值要
小, 同理未排序部分最小值要比排序部分左半部分最大值要大.
所以未排序subarray的右边界, 即end的值肯定是小于(注意是严格小于)subarray里最大值, 也小于排
序右半部分的最小值.
同理未排序subarray的左边界, 即start的值肯定是大于(同上严格大于)subarray里最小值, 也大于
排序左半部分的最大值.
所以我们从左往右, 保留当前遇到的最大值max, 并且与cur遍历到的值nums[cur]进行比较, 如果这
两个值相等, 说明当前nums[cur]最大, 顺序上没有问题, 如果nums[cur]要小于当前max, 说明这个
nums[cur]可以作为一个潜在的右边界, 一直遍历到最右边, 结束.
反之亦然.
所以我们稍微抽象一下:
从左往右, 找到最右的那个比(当前已经遍历过的所有数后找到的最大值)要小的值的indice end.
从右往左, 找到最左的那个比(当前已经遍历过的所有数后找到的最小值)要大的值的indice start.
result = end - start + 1
'''
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
if nums == None:
return 0
if len(nums) == 0 or len(nums) == 1:
return 0
maximum = float('-inf')
end = -2
for i in range(0, len(nums)):
maximum = max(maximum, nums[i])
if nums[i] < maximum:
end = i
minimum = float('inf')
begin = -1
for i in range(len(nums)-1, -1 ,-1):
minimum = min(minimum, nums[i])
if nums[i] > minimum:
begin = i
return end - begin + 1
# 0 O(nlogn), O(n)
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
sorted_nums = sorted(nums)
start = 0
end = len(nums) - 1
while start < len(nums) and nums[start] == sorted_nums[start]:
start += 1
while end >= start and nums[end] == sorted_nums[end]:
end -= 1
return end - start + 1
# 1 O(n), O(1)
# https://leetcode.com/problems/shortest-unsorted-continuous-subarray/discuss/103067/Python-O(N)-with-O(1)-space-complexity.-No-sorting
# https://leetcode.com/problems/shortest-unsorted-continuous-subarray/discuss/103057/java-on-time-o1-space
# https://leetcode.com/problems/shortest-unsorted-continuous-subarray/discuss/264474/Python-O(n)-2-Loops-and-O(1)-space
'''
Such as following example that would not get caught by first pass:
[1, 3, 7, 2, 5, 4, 6, 10] : left would catch at value 7, index: 2 and right
would catch at value 4, index: 5
But, looking at the array the function should also include 3 and 6. And this
is why we do another round of while loop.
Instead incrementing and decrementing respective, l and r, we decrement and
increment respective l and r.
Thinking about it as adjusting lower bound and upper bound is better.
This adjustment depends on two things: Minimum and maximum values of array
nums[l:r+1].
Now, we decrement l value until we find something that is lower than minimum.
Also, we increment r value until we find something that is greater than maximum.
After all that you just need to do l + r - 1.
'''
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
def find_min_max(l,r):
local_minimum = float('inf')
local_maximum = float('-inf')
for i in range(l, r + 1):
if i == len(nums):
break
local_minimum = min(local_minimum, nums[i])
local_maximum = max(local_maximum, nums[i])
return local_minimum, local_maximum
if len(nums) < 2:
return 0
l, r = 0, len(nums) -1
while l < len(nums) - 1 and nums[l] <= nums[l + 1]:
l += 1
while r > 0 and nums[r] >= nums[r -1]:
r -= 1
if l > r:
return 0
tempMin, tempMax = find_min_max(l, r+1)
while l > 0 and tempMin < nums[l-1]:
l -= 1
while r < len(nums) - 1 and tempMax > nums[r+1]:
r += 1
return r - l + 1
Last updated
Was this helpful?