zoukankan      html  css  js  c++  java
  • 【Leetcode】【Medium】Search for a Range

    Given a sorted array of integers, find the starting and ending position of a given target value.

    Your algorithm's runtime complexity must be in the order of O(log n).

    If the target is not found in the array, return [-1, -1].

    For example,
    Given [5, 7, 7, 8, 8, 10] and target value 8,
    return [3, 4].

    解题思路:

    典型的二分查找应用,此题读透,可以基本掌握二分查找的使用;

    二分查找主要需要注意以下几个方面:

    (1)如何设置循环条件(l<r 或 l <= r);

    (2)如何设置mid;

    (3)比较mid后,如何更新l 和 r;

    (4)循环结束后,l或r谁是要寻求的正确值;

    二分查找思路总结:

    1、确定循环范围的原则

      必须保证计算的范围内,包含要寻找的值;

    2、保证每次循环的更新步长最小为1

      循环移动的最小步长可能为1,也可能为2。(为2的情形:mid = (l+r)/2,即mid>=l,mid<r,而更新时选择,r = mid - 1,造成每次更新r时,步长至少为2)

      始终选择步长为1,因为步长为2逻辑思路不如步长1清晰,并且步长2在循环跳出时,对l和r的状态不确定,容易漏判边界条件;

    3、在步长为1时,始终使用l<r

      因为,当步长为1,l<r跳出循环,一定是以l=r的形式跳出的,即只要保证l或r肯定有一个满足要求,便不必考虑l=r的情况。

    4、步长为1的两种情况

      (1)如果mid是(l+r)/2,那么mid可能等于l,因此每次更新l必须为mid+1;r始终大于mid,因此更新r时,选择r=mid;

      (2)如果mid是(l+r)/2 + 1,那么mid可能等于r,因此每次更新r,必须为mid-1;l始终小于mid,因此更新时,选择l=mid;

      遇到具体问题时,一般根据实际需要倒推,比如需要每次l = mid+1,则使用(1);需要r = mid - 1,则使用(2)。

    5、循环结束的返回值

      在步长为1且l<r的条件下,循环结束时l=r,因此返回哪个都正确;

      但是如果步长和条件改变,则要根据情况变化;

    对于本题:

    1、先用二分法找左边界

      找左边界时,应该保证所查范围内,一定包含左边界,因此当mid=target时,r应该=mid,而不是mid-1,因此可以使用策略4(1);

    2、再用二分法找右边界

      找右边界时,应该保证所查范围内,一定包含右边界,因此当mid=target时,l应该=mid,而不是mid+1,因此不能使用策略4(1),要使用策略4(2);

    3、l和r跳出循环时相等,因此判断/返回哪一个都行;

    代码:

     1 class Solution {
     2 public:
     3     vector<int> searchRange(vector<int>& nums, int target) {
     4         
     5         int n = nums.size();
     6         vector<int> ret = {-1, -1};
     7         
     8         int l = 0;
     9         int r = n - 1;
    10         while (l < r) {
    11             int mid = (l + r) / 2;
    12             if (nums[mid] >= target)
    13                 r = mid;
    14             else
    15                 l = mid + 1;
    16         }
    17         if (nums[r] != target)
    18             return ret;
    19         ret[0] = r;
    20         
    21         r = n - 1;
    22         while (l < r)  {
    23             int mid = (l + r) / 2 + 1;
    24             if (nums[mid] > target)
    25                 r = mid - 1;
    26             else 
    27                 l = mid;
    28         }
    29         ret[1] = l;
    30         
    31         return ret;
    32     }
    33 };

      

  • 相关阅读:
    Visual Studio 2010 Ultimate敏捷利剑:详解Scrum
    Microsoft .Net Micro Framework 3.0 and BIC Survey(2008 WinHEC)
    Visual Studio 2010 Ultimate开发与测试敏捷特性
    博客园开发征途又添新书《.NET软件设计新思维——像搭积木一样搭建软件》出版
    《运用Microsoft Visual Studio 2010落实敏捷软件开发》CSDN大会我的Session(PPT已上传)
    北京微软.Net和博客园俱乐部Open Party两本新书交流活动(已圆满结束)
    使用ASP.Net 3.5 的Ajax与Web服务开发实例
    WCF服务在JavaScript中使用ASP.NET的AJAX方法
    浅谈MVP与ModelViewViewModel(MVVM)设计模式
    荣获“微软2009最有影响力开发者”称号
  • 原文地址:https://www.cnblogs.com/huxiao-tee/p/4391408.html
Copyright © 2011-2022 走看看