[题解]LeetCode 162. 寻找峰值 (C++)
题目
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log 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。
提示:
- 1 <= nums.length <= 1000
- \(-2^{31} <= nums[i] <= 2^{31} - 1\)
- 对于所有有效的 i 都有 nums[i] != nums[i + 1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-peak-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
题中明确要求实现时间复杂度O(log(n))的算法,同时给出了所有元素都和其相邻元素不同的保证,显然是要用二分查找。我们要找到峰值元素,也就是说要找到一个比其左右两侧的元素都要大的元素,注意nums[0]和nums[n - 1]默认满足比-1位置和n位置的大。那么,对于nums[0]和nums[n-1]特殊考虑,只要满足大于另一侧的就行了;而对于处在其余位置的,需要判断其是否是峰值元素,如果不是,判断是在下降序列还是上升序列,根据情况修改二分查找的左右边界。
时间复杂度O(log(n)),空间复杂度O(1)。
代码
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int n = nums.size();
int left = 0, right = n - 1;
while(left < right)
{
int mid = (left + right)/2;
if(mid == 0){
if(mid == n - 1)
{
return mid;
}
else
{
if(nums[mid] > nums[mid + 1]){
return mid;
}
else
{
left = mid + 1;
}
}
}
else if(mid == n - 1){
if(mid == 0)
{
return mid;
}
else{
if(nums[mid] > nums[mid - 1]){
return mid;
}
else{
right = mid - 1;
}
}
}
else{
if(nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]){
return mid;
}
else if(nums[mid] < nums[mid - 1]){
right = mid - 1;
}
else{
left = mid + 1;
}
}
}
return left;
}
};
改进
上面的一堆逻辑纯属脱裤子放屁——多此一举,我们需要搞清楚一个问题:什么情况下mid会变成0或者n-1?变成0那必然是left == 0 && (right == 0 || right == 1),这种情况下只需要判断nums[mid]和nums[mid + 1](mid + 1不会越界,看后面)的大小就行了;而mid变成n - 1是不可能发生的,因为此时left和right都必须等于n-1,根本过不了循环判定。同时,由于nums[0] > nums[-1],也就是说数组从一个上升序列开始,我们只要找到第一个满足nums[i] > nums[i + 1]的元素就行了,而且i != n - 1,在循环中甚至不需要判定下标越界。另外注意当我们发现nums[mid] > nums[mid + 1]时,需要把right变为mid,然后进行下一次循环,因为我们不能确定当前的mid就是第一个满足nums[i] > nums[i + 1]的元素,所以还需要进一步的判断。
时间复杂度和空间复杂度不变但是代码复杂度下降了XD。
代码
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int n = nums.size();
int left = 0, right = n - 1;
while(left < right)
{
int mid = (left + right)/2;
if(nums[mid] < nums[mid + 1]){
left = mid + 1;
}
else{
right = mid;
}
}
return left;
}
};
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)