每日一题-力扣(leetcode)581. 最短无序连续子数组

文章介绍了两种解决方法来找到一个整数数组中,需要升序排序以使整个数组有序的最短子数组。第一种方法是先对整个数组排序,然后比较找出不匹配的子数组;第二种方法是通过维护最大值和最小值,从两端同时遍历数组,寻找无序子数组的边界。这两种方法的时间复杂度分别为O(nlogn)和O(n)。
摘要由CSDN通过智能技术生成

题目传送门

题目描述

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

请你找出符合题意的 最短 子数组,并输出它的长度。
在这里插入图片描述

解题思路一:

调用 sort 对nums数组进行排序,然后比较对应位置的值,找出符合题意的最短子数组即可。时间复杂度为 O(nlogn)

AC代码
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int len = nums.size(), ans = 0;
        vector<int>v;
        for(auto i : nums) v.push_back(i);
        sort(nums.begin(), nums.end());
        int left = len - 1, right = 0;
        for(int i = 0; i < len; i++) {
            if(nums[i] != v[i]) {
                left = i;
                break;
            }
        }
        for(int i = len - 1; i >= 0; i--) {
            if(nums[i] != v[i]) {
                right = i;
                break;
            }
        }
        if(left >= right) return 0;
        return right - left + 1;
    }
};
解题思路二:

看了网上一位大佬的解法后,对这道题瞬间有了一种恍然大悟的感觉,无序进行排序。
我们可以假设吧这个数组分成三段,左段和右段是标准的按照升序排序好的数组,中间一段的数组虽然是无序的,但是满足中间段的最大值小于右段的最小值,最大值大于左段的最大值。
那么我们的任务就变成了找中间段的左右边界,我们分别定义为 left 和 right.,从左右两头开始遍历。
从左到右维护的是最大值 Max, 在进入右段之前,那么遍历到的nums[i] 的值都是小于Max的,而 right 就是遍历中小于Max元素的边界
同理,从右到左维护的是最小值 Min,在进入左段之前,那么遍历到的nums[i] 的值都是大于 Min 的,而 left 就是遍历中大于 Min元素的边界
时间复杂度为 O(n)

AC代码
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int len = nums.size();
        int left = 0, right = -1, Max = nums[0], Min = nums[len-1];
        for(int i = 0; i < len; i++) {
            if(nums[i] >= Max) Max = nums[i];
            else right = i;
            if(nums[len-i-1] <= Min) Min = nums[len - i - 1];
            else left = len - i - 1;
        }
        return right - left + 1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值