一个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