Day74 | 灵神 | 二分查找 寻找峰值

162.寻找峰值

162. 寻找峰值 - 力扣(LeetCode)

思路:

这道题笔者完全没有思路,不知道怎么用二分,实在有点想不通,诶,多刷吧,下面说说笔者的理解

大家可以先看一下这个视频

数组峰值 搜索旋转排序数组【基础算法精讲 05】_哔哩哔哩_bilibili

第一个难点

有点云里雾里是吧,再去看看灵神的题解,主要去看为什么 如果 i<*n*−1 且 *nums*[*i*]>nums[i+1],那么在 [0,i] 中一定存在至少一个峰值。

162. 寻找峰值 - 力扣(LeetCode)

灵神使用反证法说明了

如果 i<*n*−1 且 *nums*[*i*]>nums[i+1],那么在 [0,i] 中一定存在至少一个峰值。

而这个是我们二分的基础,这句话说明的是,如果说nums[i]>nums[i+1],那么代表在[0,i]之中一定存在至少一个峰值。

更加好理解的解释:我们首先知道数组不止一个峰值,而nums[i]>nums[i+1]时,有两个情况,要么i就是峰值,要么nums[i+1]到nums[n-1]即[i+1,n-1]都在某个峰值的右侧,注意是某个峰值的右侧,因为灵神有反证法证明了[0,i]之中必然至少有一个峰值,所以[i+1,n-1]都在某个峰值的右侧

所以[i+1,n-1]全都会被染成蓝色

灵神的提醒:

⚠常见误区:如果有多个峰值,我们无法在一开始、以及二分过程中就确定哪个峰值最终会成为答案。二分的思路只是不断地缩小范围,并最终找到其中的一个峰值。尤其在二分过程中,nums[i]<nums[i+1] 并不意味着 i 右边的第一个峰值一定会是最终答案。

第二个难点

为什么nums[n-1]即数组的最后一个元素为什么一开始不在区间内?

这是灵神的回答:因为 n-1 要么是答案,要么在答案右侧,所以 n-1 一定是蓝色,无需二分

完整代码:

这是笔者写的左闭右开的写法,由于终止条件是l==r所以返回l或者r都可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int l=0,r=nums.size()-1;
while(l<r)
{
int mid=l+(r-l)/2;
if(nums[mid]>nums[mid+1])
r=mid;
else
l=mid+1;
}
return r;
}
};