面试系列:无序的子数

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值