leetcode 581. Shortest Unsorted Continuous Subarray(最短未排序子数组)

Given an integer array nums, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order.

Return the shortest such subarray and output its length.

Example 1:

Input: nums = [2,6,4,8,10,9,15]
Output: 5
Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole array sorted in ascending order.

简言之就是找出大的排序数组中未排序的部分的长度

思路:
(1) 可以另外建一个数组,保存与nums一样的元素,但是排序。
然后一一对比,从左边遍历,发现顺序不对的index保存到start,再从右边遍历,遇到顺序不一致的index保存为end,最后未排序部分的长度为end-start+1

    public int findUnsortedSubarray(int[] nums) {
        if(nums == null || nums.length == 0) {
            return 0;
        }
        
        int n = nums.length;
        int[] tmp = nums.clone();
        Arrays.sort(tmp);
        
        int start = -1;
        int end = -2;
        
        for(int i = 0; i < n; i++) {
            if(tmp[i] != nums[i]) {
                start = i;
                break;
            }
        }
        
        for(int i = n -1; i >= 0; i--) {
            if(tmp[i] != nums[i]) {
                end = i;
                break;
            }
        }
        
        return end-start+1;
    }

(2) 简化上面的方法,从左到右应是升序的,从右到左应是降序的。
比如数组 1,2,3,XXX,9,10,11
我们知道中间这XXX的部分是需要重新排序的,才能整体升序,

所以这XXX部分的最小值unsortedMin也要比左边最右边的3大,
XXX部分的最大值unsortedMax也会比最右边的最小值9小。

然而也可以知道这个unsortedMin肯定不在最左边,不然就是正常的升序了,XXX就不从它开始了,
同理unsortedMax也不在最右边,不然XXX就不包含它了是吧。

所以,XXX部分的左边界数字应该是从右到左最后一个比unsortedMin大的数字(再往左所有数字都会比它小),
而XXX部分的右边界一定是从左到右最后一个比unsotedMax小的数字(再往右所有数字都比它大了)。

所以,从左到右,同时从右到左同时遍历数组,找出上面条件的边界即可。

注意start和end的初始化,在数组一直是正确顺序时,未排序部分的长度应该为0,即初始的end - start + 1应等于0.

    public int findUnsortedSubarray(int[] nums) {
        int n = nums.length;
        int unsortedMax = nums[0];
        int unsortedMin = nums[n-1];
        int start = -1;
        int end = -2;
        
        for(int i = 0; i < n; i++) {
            //从前往后找不排序部分的最大值
            unsortedMax = Math.max(unsortedMax, nums[i]);
            //从后往前找不排序部分的最小值
            unsortedMin = Math.min(unsortedMin, nums[n - 1 - i]);
            
            //更新最后一个比 不排序部分最大值 小的index
            //因为后面的排序部分都要比这部分的所有值大
            if(nums[i] < unsortedMax) {
                end = i;
            }
            //更新最前面一个比 不排序部分最小值 大的index
            //因为前面排序的部分必是比这部分的所有值都小的
            if(nums[n - 1 - i] > unsortedMin) {
                start = n - 1 - i;
            }
        }
        
        return (end - start + 1);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值