[leetcode]Search for a Range

34. Search for a Range

Given an array of integers sorted in ascending order, 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].
vector<int> searchRange(vector<int>& nums, int target)
{
    vector<int> ret({ -1, -1 });
    int N = nums.size();
    if (N <= 0) return ret;
    // search for the left bound
    int left = 0, right = N - 1;
    while (left < right)
    {
        // mid might == left
        int mid = left + (right - left) / 2;
        if (nums[mid] < target)
            left = mid + 1;
        else
            right = mid;
    }
    if (nums[left] != target) return ret;
    else ret[0] = left;
    // search for the right bound
    right = N - 1;
    while (left < right)
    {
        // mid might == right
        int mid = left + (right - left) / 2 + 1;
        if (nums[mid] > target)
            right = mid - 1;
        else
            left = mid;
    }
    ret[1] = right;
    return ret;
}

1.二分法計算mid:mid = left + (right - left) / 2,儘量不要使用mid = (left + right) / 2,可能會導致溢出。
2.mid = left + (right - left) / 2是向left偏移的:如果leftright中間隔着偶數個數,則mid的位置是偏向left一位的。
if (nums[mid] < target) left = mid + 1;
else right = mid;

所以當mid的值大於或等於target的時候,保持left不動,right = mid,因爲mid會向left偏移,所以最終會逼近左邊界。
3.計算右邊界的時候:
if (nums[mid] > target) right = mid - 1;
else left = mid;

一定要保證mid是向right偏移的,因此mid = left + (right - left) / 2 + 1

類似的題目:
35. Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0
int searchInsert(vector<int>& nums, int target) {
    int n = nums.size();
    int left = 0, right = n - 1;
    while (left <= right)
    {
        int mid = (left + right) / 2;
        if (nums[mid] == target)
            return mid;
        if (nums[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return left;
}

其實這類題目就是考察對C++中的lower_boundupper_bound的實現。
lower_bound是返回第一個大於或者等於val

template <class ForwardIterator, class T>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val)
{
    ForwardIterator it;
    iterator_traits<ForwardIterator>::difference_type count, step;
    count = distance(first, last);
    while (count>0)
    {
        it = first; step = count / 2; advance(it, step);
        if (*it<val) 
        {                
            first = ++it;
            count -= step + 1;
        }
        else count = step;
    }
    return first;
}

upper_bound是返回第一個大於val

template <class ForwardIterator, class T>
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& val)
{
    ForwardIterator it;
    iterator_traits<ForwardIterator>::difference_type count, step;
    count = std::distance(first, last);
    while (count>0)
    {
        it = first; step = count / 2; std::advance(it, step);
        if (!(val<*it))                 
        {
            first = ++it; count -= step + 1;
        }
        else count = step;
    }
    return first;
}

another code for search for a range: 利用lower_boundupper_bound.

vector<int> searchRange(vector<int>& nums, int target)
{
    vector<int> res(2, -1);
    int N = nums.size();
    if (N <= 0) return res;
    int count = N;
    int first = 0;
    while (count > 0)
    {
        int step = count / 2;
        int num = nums[first + step];
        if (num < target)
        {
            first += ++step;
            count -= step;
        }
        else
            count = step;
    }
    if (first >= N || nums[first] != target) return res;
    else res[0] = first;
    count = N - first;
    while (count > 0)
    {
        int step = count / 2;
        int num = nums[first + step];
        if (!(target < num))
        {
            first += ++step;
            count -= step;
        }
        else
            count = step;
    }
    res[1] = --first;
    return res;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章