题目:

峰值元素是指其值严格大于左右相邻值的元素。

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞ 。

你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

示例 1:

输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:

输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5
解释:你的函数可以返回索引 1,其峰值元素为 2;
  或者返回索引 5, 其峰值元素为 6。

提示:

  • 1 <= nums.length <= 1000
  • -231 <= nums[i] <= 231 - 1
  • 对于所有有效的 i 都有 nums[i] != nums[i + 1]

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-peak-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

一、【二分查找-爬坡法】

分析:

  • 题目中的条件是:nums[-1] = nums[n] = -∞,说明数组中一定是从小到大再到小的过程,这其中一定存在峰值,有可能只有一个;
  • 看到要求时间复杂度为O(log n) ,可以初步想到用二分查找;
  • 二分查找:找到中点所在地方,中点可能是某座山的山峰,山的下坡处,山的上坡处,如果是山峰,最后二分终止也会找到,问题关键在于二分方向,并不知道山峰在我们左边还是右边。核心在于:爬坡,如果你往下坡方向走,也许可能遇到新的山峰,但是也许是一个一直下降的坡,最后到边界。但是如果你往上坡方向走,就算最后到上边界,由于最边界是负无穷,所以也一定能找到山峰。总之,往递增的方向上,二分,一定能找到,往递减的方向只是可能找到,也许没有。
  • 二分:初始化左右边界left = 0, right = nums.length - 1,计算出mid,循环条件:left < right,比较nums[mid] 和 nums[mid +1]:

    • nums[mid] <  nums[mid + 1]:说明mid右边是上坡,mid不是峰值且右边肯定存在峰值,继续往右查找,即left = mid + 1;
    • nums[mid] >= nums[mid + 1]:说明mid右边是下坡,这可能遇到山峰,也可能遇不到,为了保险起见,不往右边找了,缩小范围往左边找,但是mid有可能就是一个峰值,即right = mid;
    • 循环结束的条件:left == right,区间缩小到一个点,肯定left或者right为峰值,返回一个即可。

java代码(left < right):

 1 class Solution {
2 public int findPeakElement(int[] nums) {
3 int left = 0, right = nums.length - 1;
4 while (left < right){
5 int mid = left + (right - left) / 2;
6 //mid右边是在上坡,右边存在峰值
7 if (nums[mid] < nums[mid + 1]){
8 left = mid + 1;
9 }else{
10 //nums[mid] >= nums[mid+1]
11 //右边是在下坡,左边一定存在峰值,mid有可能就是峰值
12 right = mid;
13 }
14 }
15 //循环结束的条件是:left == right
16 return left;
17 }
18 }

 pyhon3代码(left <= right):

三种情况:

  • mid大于它两边元素,这时mid就为一个峰值直接返回即可;
  • nums[mid] < nums[mid + 1],mid右侧在爬坡,且mid+1可能就为一个峰值,此时向右调整搜索范围,在 [mid + 1, right]范围内继续查找,即left = mid + 1;
  • nums[mid] < nums[mid - 1],mid左侧大,向左调整搜索范围,且mid-1可能为一个峰值,在 [left, mid -1]范围内继续查找,即right = mid - 1。

注意细节的处理:由于nums[-1]和nums[n]为负无穷,所以如果nums[-1]>nums[0] > nums[1],0也是一个峰值直接返回。同样,如果 nums[n-2]< nums[n-1] < nums[n],n-1也是一个峰值直接返回即可。

 1 class Solution:
2 def findPeakElement(self, nums: List[int]) -> int:
3 n = len(nums)
4 if n == 1:
5 return 0
6 # 2个特例
7 # nums[-1]和nums[n]为负无穷
8 # 故下面两种情况可以直接返回答案
9 if nums[0] > nums[1]:
10 return 0
11 if nums[n-2] < nums[n-1]:
12 return n-1
13 left, right = 0, n - 1
14 while left <= right:
15 mid = left + (right - left) // 2
16 # mid右边上坡
17 if mid < n - 1 and nums[mid] < nums[mid + 1]:
18 left = mid + 1
19 elif mid >= 1 and nums[mid] < nums[mid - 1]:
20 # mid左边在上坡
21 right = mid - 1
22 elif mid >= 1 and mid < n - 1 and nums[mid] > nums[mid - 1] and nums[mid] > nums[mid + 1]:
23 return mid
24 return -1

 二、【暴力求解】-找最大值

由于题目保证了 nums[i] != nums[i+1],故数组nums 中最大值两侧的元素一定严格小于最大值本身。因此,最大值所在的位置就是一个峰值位置。于是对数组 nums 进行一次遍历,找到最大值对应的位置进行返回即可。

java代码:

 1 class Solution {
2 public int findPeakElement(int[] nums) {
3 int ans = 0;
4 for (int i = 0; i < nums.length; i++){
5 if (nums[i] > nums[ans]){
6 ans = i;
7 }
8 }
9 return ans;
10 }
11 }

力扣162(java&python)-寻找峰值(中等)的更多相关文章

  1. 领扣(LeetCode)寻找峰值 个人题解

    峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位 ...

  2. 力扣(LeetCode)寻找数组的中心索引 个人题解

    给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法. 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和. 如果数组不存在中心索引,那么我 ...

  3. Java实现 LeetCode 162 寻找峰值

    162. 寻找峰值 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返 ...

  4. 力扣 -- 寻找两个有序数组的中位数 Median of Two Sorted Arrays python实现

    题目描述: 中文: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums ...

  5. LeetCode 162. 寻找峰值(Find Peak Element) 29

    162. 寻找峰值 162. Find Peak Element 题目描述 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元 ...

  6. Leetcode之二分法专题-162. 寻找峰值(Find Peak Element)

    Leetcode之二分法专题-162. 寻找峰值(Find Peak Element) 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1] ...

  7. LeetCode(力扣)——Search in Rotated Sorted Array2 搜索旋转排序数组 python实现

    题目描述: python实现 Search in Rotated Sorted Array2 搜索旋转排序数组   中文: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0 ...

  8. LeetCode(力扣)——Search in Rotated Sorted Array 搜索旋转排序数组 python实现

    题目描述: python实现 Search in Rotated Sorted Array 搜索旋转排序数组   中文:假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1 ...

  9. 寻找下一个结点 牛客网 程序员面试金典 C++ java Python

    寻找下一个结点 牛客网 程序员面试金典 C++ java Python 题目描述 请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继). 给定树的根结点指针TreeNode* root ...

  10. 力扣—Reorder List(重排链表)python实现

    题目描述: 中文: 给定一个单链表 L:L0→L1→…→Ln-1→Ln ,将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点 ...

随机推荐

  1. Mac安装Tomcat的Home路径

    首先,强推mac上的一个软件Homebrew,安装好以后,再安装其他软甲就只是 "brew install 软件名"这么简单了. 正文: 我安装tomcat使用的是命令行操作的,也 ...

  2. 计算机网络-DNS以及FastGitHub

    前言 你是否观察到过这种现象,在访问Github时,有的时候能正常访问,有的时候再次刷新就访问不了,那么能不能有什么办法能一直访问.答案是有,就是在DNS层面能保证一直稳定获取可用并且快速的IP,这就 ...

  3. Android线程池封装库

    目录介绍 1.遇到的问题和需求 1.1 遇到的问题有哪些 1.2 遇到的需求 1.3 多线程通过实现Runnable弊端 1.4 为什么要用线程池 2.封装库具有的功能 2.1 常用的功能 3.封装库 ...

  4. 记录--谁还没个靠bug才能正常运行的程序

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 最近遇到一个问题,计算滚动距离,滚动比例达到某界定值时,显示mask,很常见吧^ _ ^ 这里讲的不是这个需求的实现,是其中遇到了一个比较 ...

  5. 生产环境ES的一个持续转换(continuous transform)报错,问题排查

    背景:有一天突然发现,业务统计的一个数据异常,遂立即排查原因,查看后发现一个mode是continuous 的transform是stop状态:日志如下 报错时间:2023-03-26 14:05:2 ...

  6. Docker理论

    一.什么是Dcoker 相信docker是什么大家都已经比较清楚了,网上有很详细的介绍,我这里只是大概描述一下. Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足 ...

  7. 《On Java 8》笔记 2

    第十一章 内部类 Java 8 的 Lambda 表达式和方法引用减少了编写内部类的需求 外部类可以提供一个方法返回一个指向内部类的引用 链接外部类 内部类还拥有其外部类的所有元素的访问权 使用 .t ...

  8. win10注册表各种配置

    注册表教程 lesson combination of images step: 1_注册右键特定类型文件指令 step: 2_注册新建文件类型指令 step: 3_新建文件夹右键菜单 step: 4 ...

  9. KingbaseES 语句like前匹配如何使用索引

    前言 有现场同事反馈 sql语句 like 使用后缀通配符 % 不走索引. 至于执行计划没走索引的原因与KingbaseES数据库中的排序规则相关. 测试 测试环境: KingbaseESV8R6C7 ...

  10. Kingbase Create Type 语句使用

    Kingbase create type类型创建语句 说明: KingbaseES 数据库中,可以通过CREATE TYPE语句定义一种新的数据类型. 有八种形式的CREATE TYPE.它们分别创建 ...