Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >高频面试题:找出峰值元素

高频面试题:找出峰值元素

作者头像
你好戴先生
发布于 2022-05-16 07:33:03
发布于 2022-05-16 07:33:03
54100
代码可运行
举报
文章被收录于专栏:戴言泛滥戴言泛滥
运行总次数:0
代码可运行

大家好,我是戴先生 今天给大家介绍一下如何利用玄学二分法找出峰值元素 想直奔主题的可直接看思路3 题目 给定一个整数数组 求出数组中任一峰值元素的索引地址i 注意: 1、峰值元素是指其值严格大于左右相邻值的元素 2、对于所有有效的 i 都有 nums[i] != nums[i + 1] 3、如果存在多个峰值元素,返回任一峰值元素索引即可

题解

根据题目,峰值元素其实就是将数组转换为坐标轴函数之后的极大值

可以简单地归为以下三种情况

第一种情况就是数组是单调递增或递减的

这种情况只存在一个峰值元素,为数值7

第二种情况数组先单调递减(增),再单调递增(减)

这种情况存在两(一)个峰值元素

为数值7,7(5)

第三种情况数组存在多个单调递增和递减的区间

这种情况存在多个峰值元素

为数值4,7,4

思路1

高中数学告诉我们:最大值一定是极大值

所以很简单了

只要求出数组中的最大值就可以了

求出最大值的方法就多了

最简单的就是遍历所有元素

代码实现1

思路1的代码实现如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static int findPeekElement1(int[] nums) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int result = 0;
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > nums[result]) {
                result = i;
            }
        }

        return result;
    }

思路2

在思路1的基础上我们可以做一下优化

题目要求我们找出任一极大值即可

所以我们在遍历数组的时候

只要找到了符合条件(大于左边和右边的值)的数

就能直接返回结果了

唯一需要注意的是首、尾两个值的情况

因为这两个值是没有“左边”或“右边”的值

所以如果在除了首尾之外的元素中没有找到符合条件的值

只需要比较一下首尾两个值,较大者即为极大值,且是最大值

代码实现2

思路2的代码实现如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static int findPeekElement1(int[] nums) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        for (int i = 1; i < nums.length - 1; i++) {
            if (nums[i] > nums[i - 1] && nums[i] > nums[i + 1]) {
                return i;
            }
        }
        return nums[0] >= nums[nums.length - 1] ? 0 : nums.length - 1;
    }

思路3

思路1和思路2的时间负责都都是O(n)

那么有没有办法将时间复杂度优化一下呢?

给大家说一个思路

凡是遇到有序数据或有规律的区间有序数组

第一个可以尝试的方法就是玄学算法:二分法

如图所示

通过二分法找到第一个中间值mid的时候

如果nums[mid -1] < nums[mid]

那么mid或mid的右侧一定存在一个极大值

那么就可以将范围锁定到mid~end之间

同理

如果如果nums[mid -1] > nums[mid]

那么在mid或者mid的左侧必然存在一个极大值

那么就可以将范围锁定到start~mid之间

思路明确之后代码就很好实现了

而且二分算法的时间复杂度为log(n)

代码实现3

思路3的代码实现如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static int findPeekElement2(int[] nums) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int start = 0;
        int end = nums.length - 1;
        int mid;
        while (start + 1 < end) {
            mid = (start + end) / 2;
            if (nums[mid - 1] > nums[mid]) {
                end = mid;
            } else if (nums[mid + 1] > nums[mid]) {
                start = mid;
            } else {
                return mid;
            }
        }
        return nums[start] > nums[end] ? start : end;
    }

测试验证

以上分别是三个方法的时间和空间消耗对比

明显二分法再次胜出

文/戴先生@2022年05月15日

---end---

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 你好戴先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【力扣刷题】33. 搜索旋转排序数组
来源:力扣(LeetCode) 整数数组 nums 按升序排列,数组中的值 互不相同 。
jayjay
2022/11/02
2620
【力扣刷题】33. 搜索旋转排序数组
这道算法题太太太太太简单啦
题目来源于 LeetCode 上第 268 号问题:缺失数字。题目难度为 Easy,目前通过率为 50.2% 。
五分钟学算法
2019/05/21
4260
这道算法题太太太太太简单啦
一天一大 leet(计算右侧小于当前元素的个数)难度:困难-Day20200711
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质:counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
前端小书童
2020/09/24
3330
一天一大 leet(计算右侧小于当前元素的个数)难度:困难-Day20200711
剑指offer | 面试题8:旋转数组的最小数字
如下图所示,寻找旋转数组的最小元素即为寻找 右排序数组 的首个元素 nums[x] ,称 x 为 旋转点 。
千羽
2021/12/29
2580
剑指offer | 面试题8:旋转数组的最小数字
一道简单的数组遍历题,加上四个条件后感觉无从下手
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
五分钟学算法
2019/10/09
5140
一道简单的数组遍历题,加上四个条件后感觉无从下手
搞定大厂算法面试之leetcode精讲5.二分查找
搞定大厂算法面试之leetcode精讲5.二分查找 视频教程(高效学习):点击学习 目录: 1.开篇介绍 2.时间空间复杂度 3.动态规划 4.贪心 5.二分查找 6.深度优先&广度优先 7.双指针 8.滑动窗口 9.位运算 10.递归&分治 11剪枝&回溯 12.堆 13.单调栈 14.排序算法 15.链表 16.set&map 17.栈 18.队列 19.数组 20.字符串 21.树 22.字典树 23.并查集 24.其他类型题 二分搜索 时间复杂度O(logn) 步骤: 从数组中间的元素开始,如果中
全栈潇晨
2021/11/24
3540
【算法题解】 Day20 查找
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
sidiot
2023/08/26
3040
leetcode540. Single Element in a Sorted Array
You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once. Find this single element that appears only once.
眯眯眼的猫头鹰
2020/05/12
4060
我写了一个套路,助你随心所欲运用二分搜索
读完本文,可以去力扣解决如下题目: 875.爱吃香蕉的珂珂(Medium) 1011.在D天内送达包裹的能力(Medium)
labuladong
2021/09/23
1.1K0
【算法】二分法 ② ( 排序数组中查找目标值 | 二分法的经典写法 | 在排序数组中查找元素的最后一个位置 | 二分法的通用模板 )
https://leetcode.cn/problems/binary-search/
韩曙亮
2023/03/30
8170
35. Search Insert Position(二分法)
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
yesr
2019/03/14
3220
终极一战:为了编程面试!
过去常常读一个问题,然后花几分钟把它映射到我以前见过的类似问题上。如果我可以映射它,我将只关注这个问题与父问题相比有哪些不同约束。如果这是一个新问题,那么我会尝试解决它。随着时间的推移,我开发了一组问题模式,这些模式帮助我快速地将问题映射到一个已知的问题。
量化投资与机器学习微信公众号
2019/09/29
5640
终极一战:为了编程面试!
动态规划问题——最长上升子序列(LIS)(三)
上一个版本用二分法优化了时间复杂度,但其实根据数据的样本观察可知,后面的数据都是重复的,我们只需要当列表遍历到一小时数据的最后时将后面数据的最大数加入到列表即可,这样可以快速跳出循环,避免后面不必要的查找
benym
2022/07/14
1790
LeetCode 算法题系列(第一周 25道)
假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
微芒不朽
2022/09/13
6560
单调栈-LeetCode 739、287(单调栈,桶计数)
根据每日 气温 列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。 例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
算法工程师之路
2019/11/14
6460
前端leetcde算法面试套路之双指针
上一 part 刚写完二分和滑窗,他们都属于特殊的双指针方法,所以这一 part 直接汇总一下除了特殊的二分和滑窗外的其他双指针写法
js2030code
2022/11/02
5060
【C++例题 / 训练】二分算法(模板 & 例题)
以在一个升序数组中查找一个数为例,每次考察数组当前部分的中间元素,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果中间元素大于所查找的值同理,只需到左侧查找
IsLand1314
2024/10/15
1800
【C++例题 / 训练】二分算法(模板 & 例题)
二分法还需要练习练习
力扣题目链接:https://leetcode-cn.com/problems/search-insert-position/
代码随想录
2021/10/20
4430
二分查找算法,数组有序不是必要条件!
先来一段维基百科概念。“二分查找算法,也称折半搜索算法,是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。”
用户8639654
2021/07/23
1.5K0
剑指offer | 面试题38:数组中的逆序对
「归并排序」与「逆序对」是息息相关的。归并排序体现了 “分而治之” 的算法思想,具体为:
千羽
2022/02/23
1.1K0
剑指offer | 面试题38:数组中的逆序对
推荐阅读
相关推荐
【力扣刷题】33. 搜索旋转排序数组
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验