代码改变世界

一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

2013-08-30 13:39  youxin  阅读(1121)  评论(0编辑  收藏  举报

一个int数组, 比如 array[],里面数据无任何限制,要求求出 所有这样的数array[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。 

分析:
这题很直观的一个算法是,挨个的查找各个元素是否满足条件,算法的复杂度是O(n^2),太过复杂。

但如果我们在从左到右扫描数组的时候,能够维护一个candidate的数组, 该数组的元素满足: 到目前为止,这些元素都大于等于它前面的元素而小于等于到目前为止扫描到的它右边的所有元素。 容易证明, candidate数组中的元素是按照非递减顺序排列的,即对任意的i<j有cand[i] <= cand[j].

我们扫描到一个小的元素的时候,需要从右到左(从大到小)的判断cand数组中的元素是否还满足条件,知道找到第一个不大于当前扫面元素的cand.

#include<iostream>
using namespace std;

int findNum(int* arr,int n)
{
    if(arr==NULL) return 0;
    int *cand=new int[n];
    int idx=0;//记录当前cand数组元素个数
    cand[idx++]=arr[0];
    int max=arr[0],i;
    for(i=1;i<n;i++)
    {
        if(arr[i] >= max)
        {
            cand[idx++]=arr[i];
            max=arr[i];
        }
        else
        {
            while(idx>0 && cand[idx-1]>arr[i])
                idx--;
        }
    }
    for(i=0;i<idx;i++)
        cout<<cand[i]<<ends;
    cout<<endl;
    delete[] cand;
    return idx;
}

int main()
{
      int arr[20] = {1, 2, 4, 5, 6, 7, 8, 9, 10, 3, 11};
    int count = 0;
    count = findNum(arr, 11);
    cout<<count<<endl;
}

cand[idx++]=arr[0];
    int max=arr[0],i;先把

idx置0,cand[0]=arr[0]=1,max=arr[0];

i=1 cand:1,2 max=2

i=2 cand:1,2,4 max=4

i=3 cand:1,2,4,5,max=5

i=4 cand:1,2,4,5,6 max=6

i=5 cand:1,2,4,5,6,7 max=7

i=6 cand:1,2,4,5,6,7,8 max=8

i=7  cand:1,2,4,5,6,7,8,9 max=9

i=8  cand:1,2,4,5,6,7,8,9,10  max=10

i=9; arr[9]=3<max;  回退 ,回退到idx=2;因为cand[2]=4>3;cand[1]=2<3;

i=10 arr[10]=11,max=10 大于cand[2]=11;idx=3;

所有满足要求的为3:数据为:

1 ,2,11

参考:http://blog.chinaunix.net/uid-1844931-id-3335099.html