HOT100-37-最短无序连续子数组
题目描述
给你一个整数数组 nums
,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
示例 1:
1 | 输入:nums = [2,6,4,8,10,9,15] |
算法思路
这个题目难在要求$O(N)$的复杂度,如果没有这个要求,那么直接排序一遍然后比对改变的那一段区间即可,比如题目这个示例,排序后是[2, 4, 6 , 8, 9, 10, 15]
,相比起来只有[6, 4, 8, 10, 9]
变了,所以长度为5。但是要求为$O(N)$的话必然是不可以排序了。
我们注意到一个问题,如果把原始的数组分成三部分numsa, numsb, numsc
,那么numsa, numc
必然是有序且升序的,例如示例的[2, 6], [9, 15]
,问题出现在左侧遍历到4时,发现比6要小,不满足升序,说明至少从6开头的这一段数组出问题了,右侧我们采用倒序方式遍历,本应该是降序的,但同样发现[10, 9]
有问题,因此我们的目标就是:找到一个左边界,一个右边界,能够涵盖住出现问题的数组部分,现在的关键就是确定哪一部分数组需要重排,很显然,遇到4后,我们需要把4排到6的左侧,但是一定是6的紧邻左侧吗?并不是,我们需要找到6左侧一个第一个小于4的数,比如这个2,满足2->4->6
是升序才可以,不然如果出现5,6,4: 5->4->6
并不满足题意。同理右侧也需要这样处理,找到10右侧第一个大于10的数。这样的话我们只需要排序2->......<-15
即可。
其实光这样处理还是不够,因为我们没有考虑左右边界的关系,我们上面的推论建立在右边界的数一定大于左边界的基础上(15>2),但是如果是这样的情况nums=[1, 3, 5, 4, 2]
,那按照我们的处理方式只需要排序3->......<-2
,得到的结果是[1, 3, 4, 5, 2]
,并没有考虑2,3
是否需要排序,因此我们还需要考虑到这一点;
另外,左边界必须要小于”被排序数组中最小的数”, 右边界必须要大于“被排序数组中最大的数”,这个很好理解,不再解释。因此考虑以上三点,综合得到的代码:
1 | class Solution { |