力扣162(java&python)-寻找峰值(中等)
题目:
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 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) ,可以初步想到用二分查找;
- 二分查找:找到中点所在地方,中点可能是某座山的山峰,山的下坡处,山的上坡处,如果是山峰,最后二分终止也会找到,问题关键在于二分方向,并不知道山峰在我们左边还是右边。核心在于:爬坡,如果你往下坡方向走,也许可能遇到新的山峰,但是也许是一个一直下降的坡,最后到边界。但是如果你往上坡方向走,就算最后到上边界,由于最边界是负无穷,所以也一定能找到山峰。总之,往递增的方向上,二分,一定能找到,往递减的方向只是可能找到,也许没有。
- nums[mid] < nums[mid + 1]:说明mid右边是上坡,mid不是峰值且右边肯定存在峰值,继续往右查找,即left = mid + 1;
- nums[mid] >= nums[mid + 1]:说明mid右边是下坡,这可能遇到山峰,也可能遇不到,为了保险起见,不往右边找了,缩小范围往左边找,但是mid有可能就是一个峰值,即right = mid;
- 循环结束的条件:left == right,区间缩小到一个点,肯定left或者right为峰值,返回一个即可。
二分:初始化左右边界left = 0, right = nums.length - 1,计算出mid,循环条件:left < right,比较nums[mid] 和 nums[mid +1]:
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)-寻找峰值(中等)的更多相关文章
- 领扣(LeetCode)寻找峰值 个人题解
峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位 ...
- 力扣(LeetCode)寻找数组的中心索引 个人题解
给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法. 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和. 如果数组不存在中心索引,那么我 ...
- Java实现 LeetCode 162 寻找峰值
162. 寻找峰值 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返 ...
- 力扣 -- 寻找两个有序数组的中位数 Median of Two Sorted Arrays python实现
题目描述: 中文: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums ...
- LeetCode 162. 寻找峰值(Find Peak Element) 29
162. 寻找峰值 162. Find Peak Element 题目描述 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元 ...
- Leetcode之二分法专题-162. 寻找峰值(Find Peak Element)
Leetcode之二分法专题-162. 寻找峰值(Find Peak Element) 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1] ...
- LeetCode(力扣)——Search in Rotated Sorted Array2 搜索旋转排序数组 python实现
题目描述: python实现 Search in Rotated Sorted Array2 搜索旋转排序数组 中文: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0 ...
- LeetCode(力扣)——Search in Rotated Sorted Array 搜索旋转排序数组 python实现
题目描述: python实现 Search in Rotated Sorted Array 搜索旋转排序数组 中文:假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1 ...
- 寻找下一个结点 牛客网 程序员面试金典 C++ java Python
寻找下一个结点 牛客网 程序员面试金典 C++ java Python 题目描述 请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继). 给定树的根结点指针TreeNode* root ...
- 力扣—Reorder List(重排链表)python实现
题目描述: 中文: 给定一个单链表 L:L0→L1→…→Ln-1→Ln ,将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点 ...
随机推荐
- sign 单词学习 - 本质:去分开
sign 英[saɪn],美[saɪn] n. 符号; 指示牌; 手势; 征兆; 正负号; 星座 v. 签名; 签约; 打手语 词源说明(童理民) sign : 来自拉丁语signum,符号,标志,图 ...
- 【预训练语言模型】 使用Transformers库进行BERT预训练
基于 HuggingFace的Transformer库,在Colab或Kaggle进行预训练. 鉴于算力限制,选用了较小的英文数据集wikitext-2 目的:跑通Mask语言模型的预训练流程 一.准 ...
- python3 Crypto模块实例解析
一 模块简介 1.简介 python的Crypto模块是安全hash函数(例如SHA256 和RIPEMD160)以及各种主流的加解密算法的((AES, DES, RSA, ElGamal等)的集合. ...
- 全栈的自我修养: 002使用@vue/cli进行vue.js环境搭建 (使用Vue,Spring Boot,Flask,Django 完成Vue前后端分离开发)
全栈的自我修养: 使用@vue/cli进行vue.js环境搭建 Success, real success, is being willing to do the things that other ...
- 使用JdbcTemplate
1.使用JdbcTemplate的execute()方法执行SQL语句 Java代码 收藏代码 jdbcTemplate.execute("CREATE TABLE USER (user_ ...
- Handler源码解析
Handler源码解析 一.基本原理回顾 在android开发中,经常会在子线程中进行一些操作,当操作完毕后会通过handler发送一些数据给主线程,通知主线程做相应的操作. 探索其背后的原理:子线程 ...
- Android Studio导入Android 4.2.2的WiFi-Display系统源码
Sink源码概述 Miracast Sink端源码最早出现在Android 4.2.2上,通过googlesource可以很方便的查看: https://android.googlesource.co ...
- vim的使用进步
vim的使用进步 1.如果遇到命令行中无法退出的 狂按esc按键 或者也可以使用v模式下切换一下,之后按esc 保存退出 保存退出--:wq 保存:w 不保存退出:q! i--插入模式 v- 可视化模 ...
- arch xfce启用自动挂载usb设备,自动访问usb设备,自动连接usb设备
1.安装gvfs sudo pacman -S gvfs GVFS(Gnome Virtual File System)是一个用于 GNOME 桌面环境的虚拟文件系统,它提供了一种统一的方式来访问和管 ...
- 使用 GitLab CI/CD 和阿里云 CLI 自动部署前端项目
一.什么是 CI/CD? CI(持续交付)是功能迭代后自动构建.打包.校验代码格式.跑单测.单测覆盖率,常见的就是 Webpack.Rollup.ESLint等. CD(持续部署)是经过 CI 后,代 ...