[ 热题 HOT 100]---581. 最短无序连续子数组 ---双指针(升级版)

1 题目描述

给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

你找到的子数组应是最短的,请输出它的长度。

示例 1:

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

输入的数组长度范围在 [1, 10,000]。
输入的数组可能包含重复元素 ,所以升序的意思是<=。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2 解题思路

  • 解决方法:双指针(升级版)
就是要记录最后的位置呀啦啦啦

解题思路来自于题解:581. 最短无序连续子数组

初步思路,使用双指针法,指针i指向从头开始遍历,指针j从尾开始遍历。分别找到第一个逆序的位置,之后返回其长度即可。这也满足这道题“简单”的定位。但是写完之后发现事情并不是那么简单。比如下面这个例子[1,3,2,2,2]:

[ 热题 HOT 100]---581. 最短无序连续子数组 ---双指针(升级版)_第1张图片

如果遇到有重复数字的情况下,我们所谓的“第一个逆序”也就失效了。

写到这我们就可以想到,能不能换一种思路,指针i指向从头开始遍历,指针j从尾开始遍历。分别找到最后逆序的位置,这样也是能确定子数组的长度的。去确定开始的位置比较好说,如何确定最后的位置呢?

这里我们需要多设置两个变量,分别作为指针i与指针j的边界,
以指针i举例,需要找到最后一个逆序的位置,必然需要将所有的数遍历完。
在此过程中,如果有比遍历过程中最大的数更小的数,则说明存在逆序,此时更新标志位,一直到遍历完毕。这样就能记录下其边界。
反之对于指针j,采用同样的过程,如果有比遍历过程中最小的数更大的数,则说明存在逆序,此时更新标志位,一直到遍历完毕。

作者:ming-zhi-shan-you–m9RfkvKDad
链接:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/solution/581-zui-duan-wu-xu-lian-xu-zi-shu-zu-by-ming-zhi-s/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

3 解决代码

  • 解决方法:双指针(升级版) 《Java代码》
class Solution {
    public int findUnsortedSubarray(int[] nums) {
        int length = nums.length;
        
        int left = 0, right = -1;
        int max = nums[0], min = nums[length - 1];
        for(int i = 0; i < length; i++){
            //从左边开始找,找到比之前的还小的数值,证明逆序,更新标识位
            if(nums[i] < max){
                right = i;
            }
            else{
                max = nums[i];
            }
            //从右边开始找,找到比最后的那个还大的数值,证明逆序,更新 
            if(nums[length - i - 1] > min){
                left =  length - i - 1;
            } 
            else{
                min = nums[length - i - 1];
            }
        }
        //最右边的标识位减去最左边的标识位再加一
        return right - left + 1;

    }
}
  • 解决方法:双指针(升级版)《python3代码》
class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        length = len(nums)
        max = nums[0]
        min = nums[length - 1]
        left = 0
        right = -1
        for i in range (0, length):
            if nums[i] < max:
                right = i
            else:
                max = nums[i]
            if nums[length - i - 1] > min:
                left = length - i - 1
            else:
                min = nums[length - i - 1]
        return right - left + 1

你可能感兴趣的:(力扣LeetCode)