算法:C++实现先递增后递减队列的最值和单调递增队列的绝对值最小的值
2017-08-17 21:40
531 查看
下午面试,两面遇到的相同问题,当是回答的不是很好,晚上赶紧分析一下,下面两个题目是在不同轮次的面试中面试官提出的问题。
题目1:在一个先递增后递减的整型数组中,找出最大的数的下标;
题目2:在一个单调递增的整型数组中,找出绝对值最小的数的下标;
分析:乍看这两个题目似乎没有什么联系,但是仔细思考后我们可以转化为类似的一个问题,如果把题目2中的所有负数取绝度值,就变成了一个先递减后递增的整型数组中,找出最小的数的下标问题。一个求最大值的下标,一个求最小值的下标,这样我们就可以把这两个问题转化为一个问题求。
以题目1为例,可能会遇到集中情况:
数列单调递增
数列单调递减
数列先增后减
数列水平
我们知道在近似有序的数据中查找特定的元素,最常用的方法就是二分查找,这个题目同样适用二分查找,只不过中值的条件发生了一点变化。借用大佬的博客最值查找分析,中值终止的条件是中值坐标mid左边的元素值vec[mid-1]比vec[mid]小,右边的元素的值vec[mid+1]比vec[mid]大。C++的实现代码如下:
上面最长的if判断语句的意思是(直接摘抄):
(1) if(arr[mid+1]<=arr[mid]&&arr[mid-1]<=arr[mid])如果当前元素mid比左边的mid-1大,也比右边的mid+1大,那么mid就是答案。
(2) if(mid==n-1&&arr[mid-1]<=arr[mid])如果当前数组中待判断的元素只有2个元素且数组单调递增加,那么第2个元素就是答案。
(3) if(mid==0&&arr[mid+1]<=arr[mid])如果当前数组中待判断的元素只有2个元素且数组单调递减,那么第1个元素就是答案。
(4) if(mid==0&&mid==n-1) 如果当前数组中待判断的元素只有1个元素,那么这唯一的元素就是答案。
题目1:在一个先递增后递减的整型数组中,找出最大的数的下标;
题目2:在一个单调递增的整型数组中,找出绝对值最小的数的下标;
分析:乍看这两个题目似乎没有什么联系,但是仔细思考后我们可以转化为类似的一个问题,如果把题目2中的所有负数取绝度值,就变成了一个先递减后递增的整型数组中,找出最小的数的下标问题。一个求最大值的下标,一个求最小值的下标,这样我们就可以把这两个问题转化为一个问题求。
以题目1为例,可能会遇到集中情况:
数列单调递增
数列单调递减
数列先增后减
数列水平
我们知道在近似有序的数据中查找特定的元素,最常用的方法就是二分查找,这个题目同样适用二分查找,只不过中值的条件发生了一点变化。借用大佬的博客最值查找分析,中值终止的条件是中值坐标mid左边的元素值vec[mid-1]比vec[mid]小,右边的元素的值vec[mid+1]比vec[mid]大。C++的实现代码如下:
#include<iostream> #include<vector> #include<cmath> //查找最大值的坐标 int findPeakUtil(std::vector<int>&vec, int low, int high) { int mid = low + (high - low)/2; if ((mid == 0 || vec[mid-1] <= vec[mid]) && (mid == vec.size()-1|| vec[mid+1] <= vec[mid])) return mid; else if (mid > 0 && vec[mid-1] > vec[mid]) return findPeakUtil(vec, low, (mid -1)); else return findPeakUtil(vec, (mid + 1), high); } int findPeak(std::vector<int>&vec) { return findPeakUtil(vec, 0, vec.size()); } //查找绝对值最小值的坐标 int findMinAbs(std::vector<int>&vec, int low, int high) { int mid = low + (high - low)/2; /* (low + high)/2 */ if ((mid ==0||std::abs(vec[mid-1])>= std::abs(vec[mid]))&& (mid == vec.size()-1|| std::abs(vec[mid+1]) >= std::abs(vec[mid]))) return mid; else if (mid > 0 && std::abs(vec[mid-1]) < std::abs(vec[mid])) return findMinAbs(vec, low, (mid-1)); else return findMinAbs(vec, (low+1), high); } int findAbs(std::vector<int>&vec){ return findMinAbs(vec,0,vec.size()); } int main(){ int arr[10]={-1,2,5,8,9,11,6,5,4,3}; int arr1[10]={-9,-5,-3,-1,2,4,6,8,10,11}; std::vector<int> vec(arr,arr+10); int max_value=findPeak(vec); std::cout<<max_value<<std::endl; std::copy(arr1,arr1+10,vec.begin()); int minabs_value=findAbs(vec); std::cout<<minabs_value<<std::endl; return 0; }
上面最长的if判断语句的意思是(直接摘抄):
(1) if(arr[mid+1]<=arr[mid]&&arr[mid-1]<=arr[mid])如果当前元素mid比左边的mid-1大,也比右边的mid+1大,那么mid就是答案。
(2) if(mid==n-1&&arr[mid-1]<=arr[mid])如果当前数组中待判断的元素只有2个元素且数组单调递增加,那么第2个元素就是答案。
(3) if(mid==0&&arr[mid+1]<=arr[mid])如果当前数组中待判断的元素只有2个元素且数组单调递减,那么第1个元素就是答案。
(4) if(mid==0&&mid==n-1) 如果当前数组中待判断的元素只有1个元素,那么这唯一的元素就是答案。
相关文章推荐
- hdu 1233 还是畅通工程(最小生成树的Prim和Kruskal两种算法的c++实现)(prim算法详解)
- 【算法和数据结构】线性表(四)用两个栈来实现队列(C++实现)
- hdu 1233 还是畅通工程(最小生成树的Prim和Kruskal两种算法的c++实现)(prim算法详解)
- PHP实现找出有序数组中绝对值最小的数算法分析
- 算法设计之,堆,堆排序,基于最大堆的最大优先队列的实现(C++实现)
- C++实现优先队列——最小堆,d路堆及配对堆
- 算法导论-第23章-最小生成树:Prime算法(基于vector)的C++实现
- 算法学习记录五(C++)--->两个栈实现队列
- 算法与数据结构基础6:C++队列的简单实现
- openjudge滑动窗口(单调递增递减队列)
- 初学算法-基于最小堆的优先级队列C++实现
- C++最大堆实现priority_queue优先级队列(算法导论)
- 【算法和数据结构】图(三)最小生成树之Kruskal算法(C++实现)
- 用两个栈实现队列、旋转数组的最小数、斐波那契数列、青蛙跳台阶、矩形覆盖 --漫漫算法路 刷题篇
- 算法代码实现之选出第k小元素、中位数、最小的k个元素(线性复杂度),C/C++实现
- 图的深度优先搜索和广度优先搜索算法、最小生成树两种算法 --C++实现
- 最小二乘曲线拟合算法的C++实现
- 【算法和数据结构】图(二)最小生成树之Prim算法(C++实现)
- 基于算法导论6.5用最大堆实现的优先队列(C++)
- [C++ 实现最大值优先队列和最小值优先队列]