题目:给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。要求时间复杂度为O(n)
例: nums = [2,6,4,8,10,9,15] 输出:5
思路:
① 排序后对比 (不符合要求)
2 6 4 8 10 9 15
2 4 6 8 9 10 15
时间复杂度 O(nlogn) 空间复杂度 O(n)
② 技巧分析 左遍历 得右边界 右遍历得左边界
右遍历得左边界:
对于 nums[i] 一定是小于 nums[i+1]…… nums[n-1]中的最小值的 区间端点是 i+1
我们可以从左往右进行求解 但是这样的话会多次求后边的最小值 ,所以可以从右往前遍历 并维护最小值和左端点
如果 nums[i]>min 则 nums[i]应当被包含在区间内 左端点即为i
左遍历得右边界:
同理
复杂度: 时间复杂度 O(n) 空间复杂度 O(1)
代码:
# ① 排序后对比
def findUnsortedSubarray1(nums):
nums_sort = nums[:]
nums_sort.sort()
count = 0
for i in range(len(nums)):
if nums[i] == nums_sort[i]:
count += 1
else:
break
if count == len(nums):
return 0
for j in range(len(nums)-1,-1,-1):
if nums[j] == nums_sort[j]:
count += 1
else:
break
return len(nums)-count
# ② 技巧分析 左遍历 得右边界 右遍历得左边界
def findUnsortedSubarray2(nums):
n = len(nums)
if n < 2:
return 0
# 右遍历得左边界
minNum = nums[n-1]
l = n-1
for i in range(n-1, -1, -1):
if nums[i] > minNum:
l = i
minNum = min(minNum, nums[i])
# 左遍历得右边界
r = 0
maxNum = nums[0]
for i in range(n):
if nums[i] < maxNum:
r = i
maxNum = max(maxNum, nums[i])
return max(r-l+1, 0) # 注意 当本身有序时 r-l+1为负