581. 最短无序连续子数组
贴个题目:
贴个示例:
解题思路:
1、 排序+对比数组:
题目要求我们找最小的连续子数组,,而且这个最小的连续子数组排序之后能够让原数组升序,那么我们可以复制这个数组numcpy,然后进行排序升序,让result等于数组长度,从头遍历剪掉头,从后遍历剪掉尾,最后得判断result,如果result小于0,那就说明整个数组已经排好序了,所以返回0,大于0就返回result。
2、代码:
//qsort的compare函数:升序排序
int compare(const void *a,const void *b)
{
return *(int*)a-*(int*)b;
}
int findUnsortedSubarray(int* nums, int numsSize){
int *numcpy=(int*)malloc(sizeof(int)*numsSize);
memcpy(numcpy,nums,sizeof(int)*numsSize);//复制nums到numcpy中
qsort(numcpy,numsSize,sizeof(int),compare);//numcpy升序排序
int result=numsSize;//让result等于数组长度
for(int i=0;i<numsSize;i++)//从头遍历
{
if(nums[i]==numcpy[i]) result--;
else break;
}
for(int i=numsSize-1;i>=0;i--)//从未遍历
{
if(nums[i]==numcpy[i]) result--;
else break;
}
return result<0?0:result;//判断result的正负
}
3、性能分析:
时间分析:
一次循环:O(n),快速排序:O(nlogn),因此时间复杂度:O(nlogn)
空间分析:
新建了一个长度n的数组,因此空间复杂度:O(n)
4、一次遍历:
假设最小的连续数组为numsB,左边的数组numsA,右边的数组numsC,那么我们知道numsB中的元素都大于numsA,都小于numsC。
根据上面的结论,我们可以最小值用minNum,最大值用maxNum
然后从头遍历,如果当前元素的值大于maxNum,就替换maxNum,否则就让right等于当前下标,right为右边界;
紧接着从尾开始遍历,如果当前元素的值小于minNum,就替换minNum,否则就让left等于当前下标,left为右边界;
最后判断right-left是否大于0,如果大于就return right-left+1,不是就返回0
5、代码:
int findUnsortedSubarray(int* nums, int numsSize){
int maxNum=nums[0];
int minNum=nums[numsSize-1];
int left=numsSize-1;
int right=0;
for(int i=0;i<numsSize;i++)
{
if(nums[i]>=maxNum) maxNum=nums[i];
else right=i;
if(nums[numsSize-i-1]>minNum) left=numsSize-i-1;
else minNum=nums[numsSize-i-1];
}
return right-left>0?right-left+1:0;
}
6、性能分析:
时间分析:
仅仅是使用了一次遍历,因此时间复杂度是:O(n)
空间分析:
新建了常数个变量,因此空间复杂度是:O(1)