17、最短无序子数组
(Find the Minimum length Unsorted Subarray, sorting which makes the complete array sorted)
题意:
给你一个数组arr[0 … n-1],找到一个最短的子数组arr[s … e],排序这个子数组,使得整个数组有序。
Example:
1、input array [10, 12, 20, 30, 25, 40, 32, 31, 35, 50, 60],你的程序应该返回子数组的下边[3,8]。
2、input array[0, 1, 15, 25, 6, 7, 30, 40, 50],应该返回[2,5]。
解析:
首先声明,这个以生序作为有序。[1,2,3,4,5]是一个有序数组。
第一步找到候选的子数组[s,e]:
1、从左到右扫描数组,找到第一个无序的元素的位置s,(即第一个小于前一个元素的值)。
2、从右到左找到第一个无序元素的下标e,(即从右到左第一个大于前一个元素的值)
第二步、检查排序[s,e]是否使得整个数组有序,如果不是,扩大[s,e],在[s,e]中找到最大和最小的元素max和min。最大元素一定在后半部分[e+1, n-1]中的第e1的位置,最小元素在[1,s-1]的第s1位置,此时用[s1,e1]更新[s,e]。
例子:
[10, 12, 20, 30, 25, 40, 32, 31, 35, 50, 60]
第一步1,
10 < 12 < 20 < 30 > 25,得到30对应的下标s=3.
60 > 50 > 35 > 31 < 32 ,得到31对应的下标e=6.
排序[3,6]得到整个数组[10,12,20,25,20,32,32,40,35,50,60]仍然无序。下一步找到arr[3,6]的最值,max = 40,min = 25。在[0,2]中找到25的位置,25在3的位置;在[7,9]找到40的位置,40在8的位置。最后我们的[s=3,e=8]。
其实我们不用检查第一次得到的[3,6]是否满足,可以直接找到最值,进行比较,最后最值所在的位置,一定是我们最后需要排序的数组。
从上面可以看出,我们所有步都在O(n)时间完成,所有我们的时间复杂度是O(n)。
Code:
/**
*Author: xiaoran
*座右铭:既来之,则安之
*/
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<string.h>
using namespace std;
typedef long long LL;
const int MAXN = 1005;
void printUnsortedArray(int arr[],int n){
int i,s,e;
for(s=1;s<n;s++){
if(arr[s]<arr[s-1]) break;
}
if(s==n-1){
printf("Array is sorted!");
return ;
}
// printf("%d\n",s);
for(e=n-1;e>0;e--){
if(arr[e-1]>arr[e]) break;
}
//找到[s,e]之间的最值,
int maxV,minV;
maxV = minV = arr[s];
for(i=s;i<=e;i++){
if(maxV < arr[i]) maxV = arr[i];
if(minV > arr[i]) minV = arr[i];
}
//在[0,s-1]找到minV的位置
for(i = 0;i<s;i++){
if(arr[i] > minV){
s = i;
break;
}
}
//在[e+1,n-1]中找到maxV的位置
for(i=e+1;i<n;i++){
if(arr[i] < maxV){
e = i;
break;
}
}
printf("[%d,%d]\n",s,e);
}
int main()
{
int arr[] = {10, 12, 20, 30, 25, 40, 32, 31, 35, 50, 60};
int arr_size = sizeof(arr)/sizeof(arr[0]);
// printf("%d\n",arr_size);
int arr1[] = {10, 9,8,7,6,5,4,3,2,1};
int arr1_size = sizeof(arr)/sizeof(arr[0]);
printUnsortedArray(arr,arr_size);
printUnsortedArray(arr1,arr1_size);
return 0;
}