力扣581题:最短无序连续子数组
题目描述
给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
输入输出样例
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
输入:nums = [1,2,3,4]
输出:0
输入:nums = [1]
输出:0
Tips
1 <= nums.length <= 104
-105 <= nums[i] <= 105
你可以设计一个时间复杂度为 O(n)
的解决方案吗?
解法一:先对数组进行排序,再寻找改变的位置
int findUnsortedSubarray2(vector<int>& nums)
{
//首先判断数组原先是否是有序的
if(is_sorted(nums.begin(),nums.end()))
{
return 0;
}
vector<int>numsSorted(nums);
sort(numsSorted.begin(),numsSorted.end());
int left=0;
//比对原始的数组和经排序过后的数组的序号变化情况
while(nums[left]==numsSorted[left])
{
left++;
}
int right=nums.size()-1;
while(nums[right]==numsSorted[right])
{
right--;
}
return right-left+1;
}
时间复杂度为O(nlogn),空间复杂度O(n)
解法二,双指针+一次遍历
//使用双指针的方法进行实现
int findUnsortedSubarray(vector<int>& nums) {
if(nums.empty())
{
return 0;
}
int length=nums.size();
int minValue=nums[length-1];
int maxValue=nums[0];
//定义双指针
int begin=0,end=-1;
//从左往右,找到最小的不递增的序列的坐标
//从右往左,找到最大的不递减的序列的坐标
//end ,表示从左边到右边寻找最后一个递增的序列
//begin,表示从右边到左边寻找最后一个递减的序列
for(int i=0;i<length;i++)
{
//从左到右需要维持递增的序列,维持到最大值
//寻找右边界
if(nums[i]>=maxValue)
{
maxValue=nums[i];
}
else{
end=i;
}
//从右到左维持递减的序列,维持最小值、
//寻找左边界
if(nums[length-1-i]>minValue)
{
begin=length-i-1;
}
else{
minValue=nums[length-1-i];
}
}
return end-begin+1;
}
时间复杂度O(n),空间复杂度O(1)