LeetCode 热题 HOT 100 第八十六天 581. 最短无序连续子数组 用python3求解

题目地址

给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。

示例 1:
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。

示例 2:
输入:nums = [1,2,3,4]
输出:0

示例 3:
输入:nums = [1]
输出:0

提示:
1 <= nums.length <= 10^4
-10^5 <= nums[i] <= 10^5

进阶:你可以设计一个时间复杂度为 O(n) 的解决方案吗?
在这里插入图片描述
解法:一次遍历

代码参考官方题解:指路1
思路参考:指路2

我们可以假设把这个数组分成三段,左段和右段是标准的升序数组,中段数组虽是无序的,但满足最小值大于左段的最大值,最大值小于右段的最小值
那么我们目标就很明确了,找中段的左右边界,我们分别定义为leftright;
分两头开始遍历:
从左到右维护一个最大值max,在进入右段之前,那么遍历到的nums[i]都是小于max的,我们要求的right就是遍历中最后一个小于max元素的位置;
同理,从右到左维护一个最小值min,在进入左段之前,那么遍历到的nums[i]也都是大于min的,要求的left也就是最后一个大于min元素的位置。

代码实现:

class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        lenn = len(nums)
        maxn, right = nums[0], -1
        minn, left = nums[lenn-1], -1 #left的初始值设为0和-1都可以

        for i in range(lenn):
            if maxn > nums[i]: #从左往右维持最大值,寻找有边界right
                right = i
            else:
                maxn = nums[i]
            
            if minn < nums[lenn - i - 1]: #从右往左维持最小值,寻找左边界left
                left = lenn - i - 1
            else:
                minn = nums[lenn - i - 1]
        
        if right == -1: #整个数组都有序的情况
            return 0
        else: #大多数情况
            return right - left + 1


注:max部分的理解:好比列队(从低到高),左侧开始排查,维护一个升序的队列,当排查下一个同学时,需要与前面队列的最高位对比,以判断是否能维持一个升序队列。若下一个同学破坏了这个升序队列,我们就需要把他剔除出来(但不是真的剔除)。我们的目的是找右边界,即最后一个破坏这个升序队列的同学(能保证它的右侧是升序且位置是正确的)。
min部分同理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值