二分查找 是一种常用的查找算法,适用于数组规模较大且有序的序列,时间复杂度是O(LogN)。
算法的主要思路是:先从序列中间开始查找,如果目标小于中间数,则向前继续查找,如果目标大于中间数,则向后继续查找(升序的情况,降序相反)。
比如,目标值为4,数组是[1, 2, 3, 4, 6, 7, 9, 12, 18]
,二分查找过程如下
二分查找算法Java实现如下
二分查找的一些简单变种,需要我们对查找的条件进行适当调整。
峰值元素是指其值大于左右相邻值的元素。
给你一个输入数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设nums[-1] = nums[n] = -∞
。
示例 1:
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5
解释:你的函数可以返回索引 1,其峰值元素为 2;或者返回索引 5, 其峰值元素为 6。
提示:
进阶:你可以实现时间复杂度为 O(logN) 的解决方案吗?
很容易想到的一个思路就是遍历数组,只要找到第一个满足nums[i-1]<nums[i]>nums[i+1]的元素,由于上面有假设nums[-1] = nums[n] = -∞
,其实只要我们从数组第一个元素nums[0](大于nums[-1])开始,找到第一个满足nums[i]>nums[i+1]的元素即可,没有的话就返回数组最后一个元素nums[nums.length-1](大于nums[n])。
更加高效的一个思路是二分查找,在常规的二分查找算法中,一般要求数组完全有序,但是这道题给的数组并非完全有序,我们可以对二分查找的条件进行修改。
首先我们从中间mid开始,对比nums[mid]和nums[mid+1],因为题目说明不会有nums[i] != nums[i + 1],所以结果有以下两种情况。
无论哪种情况,我们都是一直往某个峰值方向找,所以当 left == right,就找到了其中一个峰值。