算法面试题,在数组中找出这样的数,它比它前面的数都大,比它后面的数都小
2014-07-17 12:51
399 查看
问题:在一个数组A
中,找出所有这样的A[i],它比它前面的所有数都要大,比它后面的数都要小
例如:如果A[8] = {1 2 3 4 5 6 7 8},则输出 1 2 3 4 5 6 7 8
如果A[8] = {8 7 6 5 4 3 2 1},则输出为空
如果A[8] = {3 5 4 2 1 6 8 7},则输出为6
这里给出四种方法,所有方法中,beg指向数组第一个元素,end指向数组中最后一个元素。
方法一:暴力搜索法
对每一个元素,判断它是否比它前面的数都大,然后判断它是否比它后面的数都小
这种方法不可行,请直接忽略!!!
对于原先的数组A
,申请一个新的数组B
,B
存放A
排序后的结果。对应位置上A[i]==B[i],则输出。
构造一个“查找表” Min
;对应位置上Min[i],存放了原数组A[i]位置往后这一部分的最小值。
一个变量Max,保存了在遍历A
时,遇到的最大值。
遍历A
,如果 A[i]>=Max (比前面的数都大),并且 A[i] <= Min[i] (比后面的数都小),输出A[i].
四:快速搜索法
在数组中,找到最小值的地址(指针、索引)MinIndex,则
1、如果MinIndex 指向最后一个元素,则原数组中所有元素均不满足,return;
2、如果MinIndex 指向第一个元素,则第一个元素满足要求,输出。
3、如果MinIndex 指向中间的某个元素,则对后半部分,递归进行上面的过程。
在上述算法中,需要设置一变量Max,保存MinIndex 前面一部分的最大值。
下面是算法的实现,已经将递归算法改为循环了。
中,找出所有这样的A[i],它比它前面的所有数都要大,比它后面的数都要小
例如:如果A[8] = {1 2 3 4 5 6 7 8},则输出 1 2 3 4 5 6 7 8
如果A[8] = {8 7 6 5 4 3 2 1},则输出为空
如果A[8] = {3 5 4 2 1 6 8 7},则输出为6
这里给出四种方法,所有方法中,beg指向数组第一个元素,end指向数组中最后一个元素。
方法一:暴力搜索法
对每一个元素,判断它是否比它前面的数都大,然后判断它是否比它后面的数都小
void ViolentWay(int *beg, int *end){ if(beg == end){ cout<<*beg<<end; return; } int *cur; for(cur = beg; cur<=end; ++cur){ int *temp; for(temp = beg; temp<cur; ++temp){<span style="white-space:pre"> </span>//与前面的数进行比较 if(*temp > *cur){ break; } } if(temp != cur){<span style="white-space:pre"> </span>// 如果是中途break出来的,则 temp!=cur ,这时要continue,对下一个数进行判断 continue; } for(temp=cur+1; temp<end+1; ++temp){<span style="white-space:pre"> </span>// 与后面的数进行比较 if(*temp < *cur){ break; } } if(temp == end+1){<span style="white-space:pre"> </span>// 两个循环安全走完,复合要求 cout<<*cur<<' '; } } cout<<endl; }方法二:排序辅助法
这种方法不可行,请直接忽略!!!
对于原先的数组A
,申请一个新的数组B
,B
存放A
排序后的结果。对应位置上A[i]==B[i],则输出。
void SortWay(int *beg, int *end){ if(beg == end){ cout<<*beg<<end; return; } int Size = end-beg+1; int *Low = new int[Size];<span style="white-space:pre"> </span>// 申请内存空间 int *High = Low; int *temp; for(temp=beg; temp<=end; ++temp){<span style="white-space:pre"> </span>// 数组复制 *High++ = *temp; } sort(Low, High);<span style="white-space:pre"> </span>// 排序 for(temp=beg, High=Low; temp<=end; ++temp,High++){ if(*temp == *High){ cout<<*temp<<' '; } } cout<<endl; delete[] Low; }方法三:“查找表”法
构造一个“查找表” Min
;对应位置上Min[i],存放了原数组A[i]位置往后这一部分的最小值。
一个变量Max,保存了在遍历A
时,遇到的最大值。
遍历A
,如果 A[i]>=Max (比前面的数都大),并且 A[i] <= Min[i] (比后面的数都小),输出A[i].
void LookupWay(int *beg, int *end){ if(beg == end){ cout<<*beg<<end; return; } int Size = end-beg+1; int *Min = new int[Size]; int *pcur, *pM; *(Min+Size-1) = *end; for(pcur=end-1, pM=Min+Size-2; pcur>=beg; --pcur, --pM){ *pcur<*(pM+1)? *pM=*pcur : *pM=*(pM+1); // 构造“查找表” } int Max=*beg; for(pcur=beg, pM=Min; pcur<=end; ++pcur, ++pM){ if(*pcur > Max){ // 修改“当前对象前面部分的最大值” Max = *beg; } if(*pcur >= Max && *pcur <= *pM){ // 判断是否符合条件 cout<<*pcur<<' '; } } cout<<endl; delete[] Min; }
四:快速搜索法
在数组中,找到最小值的地址(指针、索引)MinIndex,则
1、如果MinIndex 指向最后一个元素,则原数组中所有元素均不满足,return;
2、如果MinIndex 指向第一个元素,则第一个元素满足要求,输出。
3、如果MinIndex 指向中间的某个元素,则对后半部分,递归进行上面的过程。
在上述算法中,需要设置一变量Max,保存MinIndex 前面一部分的最大值。
下面是算法的实现,已经将递归算法改为循环了。
int *FindMax(int *beg, int *end){ int *Index = beg; int *temp; for(temp = beg; temp <=end; ++temp){ if(*temp >= *Index){ Index = temp; } } return Index; } int *FindMin(int *beg, int *end){ int *Index = beg; int *temp; for(temp = beg; temp <=end; ++temp){ if(*temp <= *Index){ Index = temp; } } return Index; } void QuickWay(int *beg, int *end, int Max=0xf0000000){<span style="white-space:pre"> </span>//Max 最大值初始化为最大负数值 if((beg == end)&&(*beg >= Max)){ cout<<*beg<<endl; return; } int *MaxIndex, *MinIndex; while(true){ MinIndex = FindMin(beg,end);<span style="white-space:pre"> </span>// 找到最小值的索引 MaxIndex = FindMax(beg, MinIndex);<span style="white-space:pre"> </span>// 找到MinIndex 前面一部分的最大值 if(*MaxIndex > Max){ Max = *MaxIndex; } if(end == MinIndex ){<span style="white-space:pre"> </span>// MinIndex 指向最后一个元素时,就可以break了,但最后一个元素也可能符合要求 if(*end >= Max){ cout<<*end; } break; } else if((beg == MinIndex)&&(*MinIndex >=Max)){<span style="white-space:pre"> </span>// MinIndex 指向第一个元素,如果它比Max大,则符合要求 cout<<*MinIndex<<' '; } beg = MinIndex + 1; } cout<<endl; }
方法 | 空间复杂度 | 时间复杂度(最好) | 时间复杂度(平均) | 时间复杂度(最坏) |
暴力搜索 | O(1) | O(N^2) | O(N^2) | O(N^2) |
排序辅助法 | O(N) | O(N) | O(NlogN) | O(N^2) |
查找表 | O(N) | O(N) | O(N) | O(N) |
快速搜索 | O(1) | O(N) | O(NlogN) | O(N^2) |
相关文章推荐
- 算法面试题之不修改数组找出重复的数字
- 给定一个整数数组,找出两个下标,要求后面下标所指的数减去前面下标所指的数之差最大
- 每日一道算法题:微软面试题:在排序数组中,找出给定数字出现的次数
- 算法题:将一个数组中所有奇数放前面和偶数放后面(不开辟新的内存空间)
- 乱序数组找出前面的都比他小后面的都比他大的数
- 在数组中找出一个数,这个数>=它前面的所有数,<它后面的所有数
- 面试题:数组后面的数减去前面的数的差最大
- 程序员面试题精选100题(29)-调整数组顺序使奇数位于偶数前面[算法]
- 一道面试题:从一个字符串中找出第一个不重复字符;算法二;
- 每天一道算法题10 找出数组中两个只出现一次的数字
- 微软,Google面试题 (29) —— 调整数组顺序使奇数位于偶数前面
- 面试题_找出数组中两个只出现一次的数字
- 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数
- 面试题精选(85):给定数组Arr[n],O(n)时间内找出每个元素左侧所有元素中位置最靠近该元素且大于该元素的元素
- 从一个数组中找出几个数,使其相加等于某个值的算法(数组元素可以重复)
- 一道面试题:从一个字符串中找出第一个不重复字符;算法一;
- 一个无序整数数组,数组元素大于5个,请用一种高效的算法找出其中最大的5个值.
- 每天一道算法题-1 找出数组中两个只出现一次的数字
- 一个数组,找出其中具有这样一个特性的数字:1、比它左边的数都大2、比它右边的数都小
- 每天一道算法题10 找出数组中两个只出现一次的数字