您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# LeetCode如何寻找峰值
## 1. 问题定义
在LeetCode的[162. 寻找峰值](https://leetcode.cn/problems/find-peak-element/)问题中,要求:
- 给定一个整数数组`nums`,其中`nums[i] ≠ nums[i+1]`
- 找到任意一个峰值元素并返回其索引
- 峰值元素指其值严格大于左右相邻值的元素
- 对于边界元素,只需满足大于一侧相邻元素即可
- 要求时间复杂度为O(log n)
示例:
输入:nums = [1,2,3,1] 输出:2(因为nums[2] = 3是峰值)
## 2. 基础解法分析
### 2.1 线性扫描法(O(n))
最直观的解法是遍历数组,找到第一个满足条件的元素:
```python
def findPeakElement(nums):
for i in range(len(nums)-1):
if nums[i] > nums[i+1]:
return i
return len(nums)-1
缺点:虽然简单,但无法满足题目要求的对数时间复杂度。
利用数组的局部有序性,可以采用类似二分查找的方法:
def findPeakElement(nums):
left, right = 0, len(nums)-1
while left < right:
mid = (left + right) // 2
if nums[mid] > nums[mid+1]:
right = mid
else:
left = mid + 1
return left
为什么二分法适用于此问题?关键在于:
if nums[mid] > nums[mid+1]:
# 向左搜索(包含mid)
right = mid
else:
# 向右搜索(排除mid)
left = mid + 1
使用left < right
而非left <= right
的原因:
- 保证循环结束时left == right
- 避免出现mid+1越界的情况
Java版本:
public int findPeakElement(int[] nums) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] > nums[mid + 1]) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
C++版本:
int findPeakElement(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[mid + 1]) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
扩展问题:在二维矩阵中寻找峰值(值大于等于所有相邻元素)
解法思路: 1. 选取中间列 2. 找到该列的最大值 3. 比较其与左右元素 4. 递归搜索左侧或右侧
如果需要找到所有峰值,则必须使用O(n)的线性扫描方法:
def findAllPeaks(nums):
res = []
if len(nums) == 1:
return [0]
if nums[0] > nums[1]:
res.append(0)
for i in range(1, len(nums)-1):
if nums[i-1] < nums[i] > nums[i+1]:
res.append(i)
if nums[-1] > nums[-2]:
res.append(len(nums)-1)
return res
提示:在面试中遇到类似问题时,建议先阐述线性解法,再逐步优化到对数复杂度解法,展示思维过程。 “`
(全文约1100字,实际字数可能因格式略有差异)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。