LC581. 最短无序连续子数组

581. 最短无序连续子数组
给你一个整数数组 nums ,你需要找出一个连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
要求时间复杂度为O(n).
在这里插入图片描述
思路
左边最长上升子数组的最大值都小于右边上升子数组的最小值。

分别从左往右和从右往左遍历,找出左右两边失效的位置,则这两个失序位置中间的数组即为需要排序的最短子数组。
关于这里的失序
1. 从左向右遍历,当前元素小于已遍历元素的最大值,此时的位置为最右边的失序位置;继续遍历,不断更新失序位置;
2. 从右向左遍历,当前元素大于已遍历元素的最小值,此时的位置为最左边的失序位置;继续遍历,不断更新失序位置;
3. 最右边失序位置减去最左边失序位置即为需要重排的最少个数。

代码实现

class Solution {
    public int findUnsortedSubarray(int[] arr) {
        int len = arr.length;
        if(len == 0 || len == 1) return 0;
        //左边的最大值
        int maxLeft = arr[0];
        //右边的最小值
        int minRight = arr[len-1];
        //从左向右遍历过程中维护的最右失序位置
        int InvalidRightPos = 0;
        //从右向左遍历过程中维护的最左失效位置
        int InvalidLeftPos = 1;
        for(int i = 1; i < len; i++) {
        	//当前遍历到的元素小于已遍历元素中的最大值,这个位置即为最右失序位置
            if(maxLeft > arr[i]) {
                InvalidRightPos = i;
            }else {	//当前遍历到的元素大于等于已遍历元素中的最大值,更新左部最大值,为当前元素值
                maxLeft = arr[i];
            }
        }
        for(int i = arr.length - 2; i >= 0; i--){
        	//当前遍历到的元素大于已遍历元素中的最小值,这个位置即为最左失序位置
            if(minRight < arr[i]){
                InvalidLeftPos = i;
            }else{	//当前遍历到的元素小于已遍历元素中的最大值,更新左部最小值,为当前元素值
                minRight = arr[i];
            }
        }
        //如果有序,返回应该为0,所以初始化InvalidRightPos、InvalidLeftPos这两个变量时要保证数组有序时返回为0.
        return InvalidRightPos - InvalidLeftPos + 1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值