LeetCode Hot 100-581最短无序连续子数组

给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
你找到的子数组应是最短的,请输出它的长度。
示例 1:
输入: [2, 6, 4, 8, 10, 9, 15]
输出: 5
解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
说明 :
输入的数组长度范围在 [1, 10,000]。
输入的数组可能包含重复元素 ,所以升序的意思是<=。

  1. 我想的解法,排序+左右分别找边界

首先排序,为什么要排序呢,我们看例子,如果要确定一个连续的子数组,意思就是
要找到一个子数组,并且只排序这个子数组就相当于对整个数组进行了排序,也就是说,这个子数组的左边和右边顺序都是固定的,并且都是有序的,那么我们就可以分别遍历左边和右边,找到第一个不同的数,差值+1就是最后结果。

我们看例子

是否排序 顺序
2->6->4->8->10->9->15
2->4->6->8->9->10->15
截止位 2->↑->X->X->X->↑->15

那么就是两个↑的下标差+1,也就是5 - 1 + 1 = 5

代码

class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        if not nums:
            return 0
        sorted_nums = sorted(nums)
        # 初值为0,-1是为了满足排序前数组和排序后数组都相同,也可以用right + 1 - left输出结果0
        left = 0
        right = -1
        for i in range(len(nums)):
            if sorted_nums[i] != nums[i]:
                left = i
                break
        for i in range(len(nums) - 1, -1, -1):
            if sorted_nums[i] != nums[i]:
                right = i
                break
        return right + 1 - left
  1. 大佬的解法
    初始化max_nums=nums[0]为当前遍历到的最大值
    初始化min_nums=nums[-1]为当前遍历到的最大值
    left为左边界
    right为右边界
    首先我们从左边开始遍历,如果找到比max_nums大的数,就把这个数赋给max_nums,保证max_nums是遍历过的最大的数,如果比max_nums小,就更新right到当前位置,因为当前位置有比目前的最大值小的数,需要排序,遍历一遍之后得到右边界right
    同理,找到左边界left
    那么同样结果也是right-left+1

代码

class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        max_nums = nums[0]
        min_nums = nums[-1]
        left = 0
        right = -1
        for i in range(len(nums)):
            if max_nums > nums[i]:
                right = i
            else:
                max_nums = nums[i]
            if min_nums < nums[len(nums) - 1 - i]:
                left = len(nums) - 1 - i
            else:
                min_nums = nums[len(nums) - 1 - i]
        return right + 1 - left

好像也没差
在这里插入图片描述

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray

你可能感兴趣的:(LeetCode,LeetCode-Hot)