leetcode162

题目地址

162. 寻找峰值

题目分析

O ( n ) O(n) O(n)的算法很好想,很简单,再次不多赘述了;但是 O ( log ⁡ n ) O(\log n) O(logn)​​的算法就抓破脑袋也写不出来,这就是差距吧。​​

二分的思路如下:先判断某个位置i上的数是不是峰值(peak),如果不是,再判断i和i+1位置上的数的大小,如果nums[i+1]>nums[i],那么i+1之后一定有峰值(其实i之前也可能有峰值,但是可能存在0到i一直是单调上升的情况),反过来讲如果nums[i]>nums[i+1],那么i之前一定有峰值,反而是i+1之后可能存在单调递减的情况,根据这个原则可以舍弃掉i之前或者i+1之后的区间,使用二分查找优化算法。

题解

具体的见官解。下面是我写的。

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int n = nums.size();
        auto get = [&](int i) -> pair<int, int> {
            if (i == -1 || i == n) {
                return {0, 0};
            }
            return {1, nums[i]};
        };

        int p = 0, q = nums.size()-1;
        int mid = (p+q)/2;
        while(!(get(mid) > get(mid+1) && get(mid) > get(mid-1)))
        {
            mid = (p+q)/2;
            if(get(mid) < get(mid+1))
                p = mid + 1;
            else
                q = mid - 1;
        }
        return mid;
    }
};

总结

这题不仅学了算法,还学了C++的语法知识,总结一下。

解法二代码如下:

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int n = nums.size();
        int idx = rand() % n;

        // 辅助函数,输入下标 i,返回一个二元组 (0/1, nums[i])
        // 方便处理 nums[-1] 以及 nums[n] 的边界情况
        auto get = [&](int i) -> pair<int, int> {
            if (i == -1 || i == n) {
                return {0, 0};
            }
            return {1, nums[i]};
        };

        while (!(get(idx - 1) < get(idx) && get(idx) > get(idx + 1))) {
            if (get(idx) < get(idx + 1)) {
                idx += 1;
            }
            else {
                idx -= 1;
            }
        }
        
        return idx;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/find-peak-element/solution/xun-zhao-feng-zhi-by-leetcode-solution-96sj/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其中有两个知识点:

  1. get函数的用法。是一个lambda表达式,基本形式是“[捕获变量] (参数表) {函数体}”,具体见[1]。(其实我没怎么看懂,发现自己对于C++其实一无所知)

  2. pair类比较大小,先按照.first比较,如果.first相等,再按照.second比较。

参考资料

[1] Lambda expressions

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值