力扣 162. 寻找峰值

题目来源:https://leetcode-cn.com/problems/find-peak-element/

大致题意:
给出一个数组,返回峰值元素的下标。峰值元素就是极大值,其大于左边的元素和右边的元素。峰值元素可能有多个,返回任意一个即可

思路

如果不是题目要求算法的时间复杂度为 O(logn),那直接遍历一遍就完事了

考虑到当前元素与左右元素的大小,有四种情况

  1. 当前元素 小于 左边元素,也 小于 右边元素,当前处于坡底,为极小值,这时候要找坡顶往左往右差别不大
  2. 当前元素 小于 左边元素,但 大于 右边元素,当前处于下坡状态,要找坡顶需要往左边
  3. 当前元素 大于 左边元素,也 大于 右边元素,当前处于坡顶,为极大值,直接返回
  4. 当前元素 大于 左边元素,但 小于 右边元素,当前处于上坡状态,要找坡顶需要往右边

于是按照这个方法找坡顶就行,但是这也不是 O(logn) 的算法

二分

在刚刚的四种情况中,可以发现如果出现 2,那么接下来该位置右边的部分就不会再遍历到了(因为想到右边需要从当前位置查过去,但是只要到当前位置就一定是往左走);同样,如果出现 4,那么左边的部分就不会遍历到。

那如果我们再令出现情况 1 时,固定朝一个方向走,如固定朝右走,这就是二分了

代码:

	public int findPeakElement(int[] nums) {
        int ans = binartSearch(nums);
        return ans;
    }

    public int binartSearch(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            // 处于峰值
            if (compare(nums, mid, mid - 1) > 0 && compare(nums, mid, mid + 1) > 0) {
                return mid;
            }
            // 若小于右边元素,往右半部分查
            if (compare(nums, mid, mid + 1) < 0) {
                left = mid + 1;
            // 大于右边元素,往左半部分查
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
    // 比较两个索引处的值大小
    public int compare(int[] nums, int idx1, int idx2) {
        // 索引为 -1 和 n 处,都当无限小处理
        if (idx1 == -1) {
            return -1;
        } else if (idx2 == nums.length) {
            return 1;
        }
        return nums[idx1] > nums[idx2] ? 1 : -1;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三更鬼

谢谢老板!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值