Every day a Leetcode
题目来源:162. 寻找峰值
解法1:STL
代码:
class Solution {
public:
int findPeakElement(vector<int>& nums) {
return max_element(nums.begin(), nums.end()) - nums.begin();
}
};
复杂度分析:
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(1)。
解法2:二分查找
代码:
/*
* @lc app=leetcode.cn id=162 lang=cpp
*
* [162] 寻找峰值
*/
// @lc code=start
// 二分查找
// class Solution
// {
// public:
// int findPeakElement(vector<int> &nums)
// {
// int n = nums.size();
// int left = 0, right = n - 1;
// int ans = -1;
// while (left <= right)
// {
// int mid = (left + right) / 2;
// // 辅助函数,输入下标 i,返回一个二元组 (0/1, nums[i])
// // 方便处理 nums[-1] 以及 nums[n] 的边界情况
// function<pair<int, int>(int)> get = [&](int index) -> pair<int, int>
// {
// if (index == -1 || index == n)
// return {0, 0};
// return {1, nums[index]};
// };
// if (get(mid - 1) < get(mid) && get(mid) > get(mid + 1))
// {
// ans = mid;
// break;
// }
// if (get(mid) < get(mid + 1))
// left = mid + 1;
// else
// right = mid - 1;
// }
// return ans;
// }
// };
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])
right = mid; // 峰顶行号 <= i
else
left = mid + 1; // 峰顶行号 > i
}
return left;
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(logn),其中 n 是数组 nums 的长度。
空间复杂度:O(1)。
拓展题:Leetcode 1901. 寻找峰值 II
链接:1901. 寻找峰值 II
二分包含峰顶的行号 i:
- 如果 mat[i] 的最大值比它下面的相邻数字小,则存在一个峰顶,其行号大于 iii。缩小二分范围,更新二分区间左端点 left。
- 如果 mat[i] 的最大值比它下面的相邻数字大,则存在一个峰顶,其行号小于或等于 i。缩小二分范围,更新二分区间右端点 right。
代码:
/*
* @lc app=leetcode.cn id=1901 lang=cpp
*
* [1901] 寻找峰值 II
*/
// @lc code=start
// 二分查找
class Solution
{
public:
vector<int> findPeakGrid(vector<vector<int>> &mat)
{
if (mat.empty())
return {};
int m = mat.size(), n = mat[0].size();
int left = 0, right = m - 1;
while (left < right)
{
int i = (left + right) / 2;
int j = indexOfRowMax(mat[i]);
if (mat[i][j] > mat[i + 1][j])
right = i; // 峰顶行号 <= i
else
left = i + 1; // 峰顶行号 > i
}
return {left, indexOfRowMax(mat[left])};
}
// 辅函数 - 返回行中最大元素的下标
int indexOfRowMax(const vector<int> &row)
{
return max_element(row.begin(), row.end()) - row.begin();
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(nlogm),其中 m 和 n 分别为 mat 的行数和列数。需要二分 O(logm) 次,每次二分需要 O(n) 的时间寻找 mat[i] 最大值的下标。
空间复杂度:O(1)。仅用到若干额外变量。