• 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都是需要考虑的,还是需要根据题目的意思来吧,这道题主要是往中间夹。

  • 相关阅读:
    Activity的活动Menu和上下文Menu使用示例
    drawable之scale and rotate代码示例
    密度无关和缩放比例无关定义
    [前端优化]使用Combres合并对js、css文件的请求
    不同版本的SQL Server之间数据导出导入的方法及性能比较
    SqlBulkCopy加了事务真的会变快吗?
    ASP.NET Web Forms 4.5的新特性(二):针对HTML5的更新和Unobtrusive Validation
    MVC3缓存之一:使用页面缓存
    MVC3缓存之三:MVC3中的局部缓存(Partial Page)
    ASP.NET Web Forms 4.5的新特性(三):Model Binding
  • 原文地址:https://www.cnblogs.com/cold-windy/p/11875590.html
Copyright © 2020-2023  润新知