leetcode581. 最短无序连续子数组

该博客主要介绍了LeetCode 581题的解决方案,即如何找到使整个数组升序排序所需的最短无序连续子数组。文章提到了两种方法:一是使用排序,时间复杂度为O(nlogn),空间复杂度为O(nlogn);二是通过两次扫描,时间复杂度为O(n),空间复杂度为O(1)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/

题意:

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

请你找出符合题意的 最短 子数组,并输出它的长度。

方法:左右坐标往中间夹,找到最短长度,由于进行了排序时间复杂度为O(nlogn) ,并且使用了一个向量存储向量,空间复杂度为O(nlogn)

class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        vector<int> vct(nums);//存储一个等长的数组
        sort(vct.begin(),vct.end());//升序排序
        int len = nums.size();//记录数组长度      
        int left=0,right=len-1;//左侧坐标,右侧坐标
        while(left<len)
        {
            if(vct[left]!=nums[left])//从左到右,如果出现第一个在数组中不相等的元素就退出循环
            {
                break;
            }
            left++;//从左到右
        }
        if(left==len) return 0;
        while(right>=0)
        {   
            if(vct[right]!=nums[right])//从右到左,如果出现第一个在数组中不相等的元素就退出循环
            {
                break;
            }
            right--;//从右到左
        }
        return right-left+1;
    }
};

方法二:使用两次扫描,找到最左侧比最短子数组中最小的元素大的元素,找到最右侧比最短子数组中最大的元素小的元素,利用这两个元素的位置,找到缝隙的数目,在它们缝隙的数目的基础上加上1,就是最短长度。使用了两边扫描套用了两次一重循环,时间复杂度O(n),空间复杂度O(1)

class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int len = nums.size();//元素个数
        int right = 0,left = len;//右侧坐标从0开始扫描,左侧坐标从len开始扫描
        int minx = nums[len-1],maxx = nums[0];//存储扫描过的最小值,存储扫描过的最大值
        for(int i=len-1;i>=0;i--)//从右往左扫描,找的是出现的需要排序的数字的位置
        {
            if(nums[i]>minx)//如果对应的值比扫描过的最小的大,说明这个位置的值是需要排序的
                left = i;
            minx = min(minx,nums[i]);//保存扫描过的最小值,并存储
        }
        for(int i=0;i<len;i++)
        {
            if(nums[i]<maxx)//如果对应的值比扫描过的最大的大,说明这个位置的值是需要排序的
                right = i;
            maxx = max(maxx,nums[i]);//保存扫描过的最大值,并存储
        }
        return max(right-left+1,0);//如果不存在,right-left自然会小于0,之所以加1是因为项的个数一般都会比空隙大1
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值