581.最短无序连续子数组

一、题目描述

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

你找到的子数组应是最短的,请输出它的长度。

示例 1:

1
2
3
输入: [2, 6, 4, 8, 10, 9, 15]
输出: 5
解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。

说明 :

  1. 输入的数组长度范围在 [1, 10,000]。
  2. 输入的数组可能包含重复元素 ,所以升序的意思是<=。

二、题解

1.算法描述

  • 排序+逐位异或+双指针扫描
  • 双指针

2.个人分析

  • 首先利用快速排序数组进行升序排序,然后与原数组逐位异或,位置没变的元素就会变成0,然后利用头尾指针扫描,每遇到0,就将数组长度减一,头尾指针都遇到不为零的数时,停止扫描
  • 总结时发现,只利用双指针就行了,头尾指针向中间扫描时,头指针扫描的数应该是越来越大的,而尾指针扫描的数应该是越来越小的,当头指针的后一个数比当前位置的数小时,头指针就应该停下了,尾指针亦然;当头尾指针相遇,则表明这是一个完全有序的数组,所以返回0.

3.代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
   int compare1(const void *a, const void *b)
{ //升序
return (*(int *)a - *(int *)b);
}
int findUnsortedSubarray(int *nums, int numsSize)
{
if (numsSize == 1)
{
return 0;
}
int *help = (int *)malloc(numsSize * sizeof(int));
int i;
for (i = 0; i < numsSize; i++)
help[i] = nums[i];
qsort(nums, numsSize, sizeof(int), compare1);
//逐位异或
for (i = 0; i < numsSize; i++)
nums[i] ^= help[i];
int m = 0, n = numsSize - 1;
int res = numsSize;
//双指针
while ((nums[m] == 0 || nums[n] == 0) && m <= n)
{
if (nums[m] == 0)
{
res--;
m++;
}
if (nums[n] == 0)
{
res--;
n--;
}
}
if (res < 0) //如果队列有序,res=-1,那么应该返回0
return 0;
return res;
}