zoukankan      html  css  js  c++  java
  • leetcode162. 寻找峰值

    给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。

    数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

    你可以假设 nums[-1] = nums[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。

    说明:

    你的解法应该是 O(logN) 时间复杂度的。

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

    解答

    写在前面注意这道题的条件是nums[-1] = nums[n] = -∞ ,也就是说,左右两边是最小值,那么只要数组中有个值就肯定会有峰值,毕竟如果画个图像的话,肯定会出现那个转折点,高数忘得差不多了,应该是斜线为0,一次函数中的k。

    解法1:可以直接遍历,因为左右两边都是最小值,所以第一个元素就是递增,那么只要有一个减小的元素,说明就出现了峰值。

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

    也可以从两边同时开始,但是复杂度都是一样的,都是On,这又说明了,在一个(0~n)的循环中,如果你缩短循环次数,但是你每次循环要做的个数变成2倍的话,还是一样的,说明一次做多个但是只要是你都做了,就是并不会降低复杂度,只有某些元素直接跳过,这样才会降低复杂度。

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

    解法2:利用二分法,有关二分法的变种实在太多,每次都会又新的发现,你以为掌握的,其实实在是太少,

    1.纯正的二分查找是利用数组有序而将双指针逼近查找有没有命中target,这是最初学习的,我一般喜欢在while循环里面判断条件

    while(l<=r) 但是这样写要非常注意最后的结果究竟是l还是r,因为最后跳出循环的时候l,r是不相同的,所以这里要注意。

    2.l,r,mid的关系,这三个的关系十分烦人且难搞,究竟l=mid+1,还是l=mid,还是说r=mid-1,r=mid,这都是需要考虑的,尤其是循环判断条件的l是不是包括等于r的情况,不然很有可能是跳不出循环的,一般来说l==r 是要配合mid+1,mid-1使用的,不然可能会出现l==r,然后一直死在这里,

    一般l<r,应该是可以用mid+1,mid的,也即是可以不用强迫每一步都跳过边界。

    这里提供两种的二分。

     1 class Solution {
     2     public int findPeakElement(int[] nums) {
     3         int l=0;
     4         int r=nums.length-1;
     5         while(l<r)
     6         {
     7             int mid=l+(r-l)/2;
     8             if(nums[mid]<nums[mid+1])
     9                 l=mid+1;
    10             else 
    11                 r=mid;
    12         }
    13         return l;
    14     }
    15 }
    View Code
     1 class Solution {
     2     public int findPeakElement(int[] nums) {
     3         int l=0;
     4         int r=nums.length-1;
     5         while(l<=r)
     6         {
     7             int mid=l+(r-l)/2;
     8             if(mid<r&&nums[mid]<nums[mid+1])
     9                 l=mid+1;
    10             else if(mid>l&&nums[mid]<nums[mid-1])
    11                 r=mid-1;
    12             else
    13                 return mid;
    14         }
    15         return l;
    16     }
    17 }
    View Code

    总之,二分的条件还是比较多的,需要自己小心,要不要加等号,要不要+1,-1都是需要考虑的,还是需要根据题目的意思来吧,这道题主要是往中间夹。

  • 相关阅读:
    swift延时执行
    Swift3.0 — CocoaAsyncSocket客户端(Socket通信)
    SnapKit配置过程
    iOS App图标和启动画面尺寸
    mac升级到10.13 CocoaPods不能使用
    上传app到app store遇到 An error occurred uploading to the iTunes Store.(iTunes Store Operation Failed)的解决方法
    swift高斯模糊的自定义view
    Swift 实现部分圆角
    android 代码设置、打开wifi热点及热点的连接
    自定义android Dialog
  • 原文地址:https://www.cnblogs.com/cold-windy/p/11875590.html
Copyright © 2011-2022 走看看