您的位置:首页 > 其它

【Leetcode】【Medium】Search for a Range

2015-04-04 02:28 323 查看
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跳出循环时相等,因此判断/返回哪一个都行;

代码:

class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {

int n = nums.size();
vector<int> ret = {-1, -1};

int l = 0;
int r = n - 1;
while (l < r) {
int mid = (l + r) / 2;
if (nums[mid] >= target)
r = mid;
else
l = mid + 1;
}
if (nums[r] != target)
return ret;
ret[0] = r;

r = n - 1;
while (l < r)  {
int mid = (l + r) / 2 + 1;
if (nums[mid] > target)
r = mid - 1;
else
l = mid;
}
ret[1] = l;

return ret;
}
};


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: