每日一题局部最小值问题
Posted 唐宋xy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一题局部最小值问题相关的知识,希望对你有一定的参考价值。
局部最小值问题
题目
给定一个无序数组,相邻的数并不相等,那么就会产生很多个局部最小的值,找到任意一个局部最小的值的位置返回
局部最小:一个数满足小于相邻的左边的数和小于相邻的右边的数
例如:arr=[5,2,3,1,4,6,10,9,20], 返回:2或1或9任意一个都可以
解析
-
关键字:无序数组、相邻的数不相等、找到任意一个局部最小
-
使用的算法:因为给定的是无序数组,所以看起来不符合前面说到的可以直接使用二分查找算法,但是根据题意,可以将计算的逻辑分为两种情况:
-
第一种:直接判断第一个数或最后一个数是否小于相邻的数,如果小于,那么直接返回
-
第二种:如果第一个数和最后一个数都不小于相邻的数,那么数组的趋势如下所示:
开头和结尾的趋势是下降和上升,那么我们是否在中间的位置找到一个上升或下降的位置,就找到了局部最小。如何快速的找到对应的位置呢?
-
还是可以使用二分查找法,不过这里只是用二分查找的框架流程,具体的判断条件是单独实现
-
-
算法逻辑:
-
判断第一个数和最后一个数是否为局部最小的数
-
如果不是,那么查看中间的数mid和相邻的数进行比较
-
如果大于mid-1,那么继续向左边的子数组递归寻找
因为右边可能是连续上升的一连串数,而左边的子数组是有下降和上升两种不同的趋势,所以必定有局部最小值
-
如果大于mid+1,那么继续向右边的子数组递归寻找
因为左边有两个下降,所以可能左边都是连续下降的一连串数,而右边的子数组是有下降以及后面的上升的两种不同的趋势,所以必定是有局部最小值
-
-
-
代码实现
public static int getLessIndex(int[] arr)
if(arr == null || arr.length == 0)
return -1;
// 判断开头的数是否满足局部最小
if(arr.length == 1 || arr[0] < arr[1])
return 0;
// 判断结尾的数是否满足局部最小
if(arr[arr.length - 1] < arr[arr.length - 2])
return arr.length - 1;
// 如果到这里,那么说明0~1是下降的, arr.length-2 ~ arr.length-1是上升的,那么在数组的中间必定有局部最小的数
// 直接二分查找
int L = 1;
int R = arr.length - 2;
while (L <= R)
int mid = L + ((R - L) >> 1);
if(arr[mid] > arr[mid + 1])
// 向右边子数组继续找
L = mid + 1;
else if(arr[mid] > arr[mid - 1])
// 说明当前的趋势是上升的,因为前两个数是下降的,所以向左边数组寻找
R = mid - 1;
else
// 因为题目中说明了没有相等的数,说明mid小于左边并且也小于右边,直接返回
return mid;
return -1;
以上是关于每日一题局部最小值问题的主要内容,如果未能解决你的问题,请参考以下文章