[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;
}
Leetcode 443题是关于压缩字符串的问题。题目要求我们对给定的字符数组进行原地修改,使其变为压缩后的形式,并返回压缩后的数组长度。 解题的思路是使用双指针来遍历数组。指针j从第二个元素开始遍历,判断当前元素是否与前一个元素相同。如果相同,则计数器count加1;如果不同,则需要将计数的字符放在后面,并更新指针i的位置。当计数器count大于1时,需要将count转换为字符串,并依次放在后面的位置上。最后返回指针i的位置,即为压缩后的数组长度。 下面是示例代码: ``` class Solution(object): def compress(self, chars): n = len(chars) count = 1 i = 0 for j in range(1, n): if j < n and chars[j-1 == chars[j]: count += 1 else: chars[i = chars[j-1] i += 1 if count > 1: for m in str(count): chars[i = m i += 1 count = 1 return i ``` 这样就可以实现对给定字符数组的原地压缩,并返回压缩后的数组长度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [LeetCode第 443 题:压缩字符串(C++)](https://blog.csdn.net/qq_32523711/article/details/109106406)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [LeetCode刷题记录——第443题(压缩字符串)](https://blog.csdn.net/bulo1025/article/details/86561588)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值