题目:

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

给你一个整数数组 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. C++标准库字符串流sstream

    sstream与strstream 在C++有两种字符串流,一种在<strstream>中定义,另一种在<sstream>中定义,两者的区别如下: strstream里包含st ...

  2. 生成文件名为系统时间的C源码实例

    一 最近遇到了一个需要根据时间记录文件名的.先写一个实例来实战: #include<stdlib.h> #include<time.h> #include<stdio.h ...

  3. dbvisualizer不能执行pl/sql块

    如果是如下语句: begin          dbms_output.put_line('Hello World!'); end; 控制台会报错 解决方案:语句改写为如下 --/ begin    ...

  4. XMLSpringEclipseWebCache

    XMLSpringEclipseWebCache XMLSpy编辑工具中如何设置XML的DTD/XSD校验指向本地,而不要直接指向网络去? 前提:在不修改XML的条件下,修改XML的,不要这个,这个变 ...

  5. Redis安装(Linux CentOS)

    1. 环境介绍 主机系统:CentOS Redis版本:7.0.10 2. 安装过程 检查 GCC 版本 gcc -v redis 6.0 以上需要 gcc 5.3,升级 gcc.如果安装的redis ...

  6. KingbaseES 数据库CPU使用率过高问题与解决

    前言 本文介绍生产环境中CPU使用率高的常见原因,以及在CPU使用率高问题上的可能解决措施. 本文主要内容: 关于用于识别高CPU使用率的工具,例如kwr报告中DB CPU指标.kmonitor和sy ...

  7. IntelliJ IDEA 设置类和方法注释

    一.在创建类和文件的时候加注释 1.创建类 在右侧输入: 1 /** 2 * 3 * @author ${USER} 4 * @date ${YEAR}-${MONTH}-${DAY} ${TIME} ...

  8. 实现一个简单的echarts词云图PythonFlask

    cloud.html 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta char ...

  9. #循环节,gcd#JZOJ 5362 密码

    题目 询问一个排列\(A\)是否能够通过\(A_i=A_{A_i}\)得到, 同时还要满足给定的两个数通过加减或者交换能够得到已知的两个数 分析 下面的就是要保证\(\gcd\)相同,但是还有上面的操 ...

  10. 高能有料 | 第二届OpenHarmony技术大会议程速递

       第二届开放原子开源基金会OpenHarmony技术大会如约而至 让我们一起 开封无限惊喜的技术成果 开放无限前沿的议题干货 开启无限可能的未来之门 点击此处报名参会!