LC581(hot100). 最短无序连续子数组(技巧分析-二次遍历-中等)

LC581. 最短无序连续子数组

题目:给你一个整数数组 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为负

路虽远,行则将至。事虽难,做则必成 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值