【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 };

 

 

 

  

 

posted @ 2015-04-04 02:28  胡潇  阅读(127)  评论(0编辑  收藏  举报