LC34. 在排序数组中查找元素的第一个和最后一个位置---个人见解

【题目描述】

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

【分析】

给的是输入是vector,要求返回输出的也是vector。

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

    }
};

vector在还没有分配任何空间时还不能像数组一样用下标形式去访问vector的。


这道leetcode题有两种写法。

1、不用查找到的左边界作为下标访问vector。这里就需要设变量leftBorder和rightBorder来判断,nums中是否有target.


class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftBorder = getLeftBorder(nums, target);
        int rightBorder = getRightBorder(nums, target);
        if (leftBorder == -2 || rightBorder == -2) return {-1,-1};
        else if (rightBorder - leftBorder > 1 ) return {leftBorder+1, rightBorder-1};
        return {-1,-1};
    }
private:
    int getLeftBorder(vector<int>& nums, int target) { // 找左边界
        int left = 0;
        int right = nums.size() - 1;
        int leftBorder = -2;//记录leftBorder没有被赋值的情况
        while (left <= right) {
            int mid = left + (right - left ) / 2;
            if (nums[mid] >= target)
            {
                right = mid -1;
                leftBorder = right;
            }
            else 
                left = mid + 1;
        }
        return leftBorder;

    }
    int getRightBorder(vector<int>& nums, int target) { //找右边界
        int left = 0;
        int right = nums.size() - 1;
        int rightBorder = -2; // 记录一下rightBorder没有被赋值的情况
        while (left <= right) {
            int mid = left + (right - left ) / 2;
            if (nums[mid] <= target) {
                left = mid + 1;
                rightBorder = left;
            }
            else{
                right = mid - 1;
            }
        }
        return rightBorder;
    }
    
};

2、利用查找到的左边界作为下标访问vector。此时直接调用两个二分的模板,就能得到左右边界,然后利用左边界l,判断nums[l]是否等于target。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.size() == 0) return{-1,-1};
        //nums.resize(100005);
        int l = 0, r = nums.size()-1; 
        while (l < r) { //循环结束l=r,此时l或者r的值即为左边界
            int mid = l+(r-l)/2;
            if (nums[mid] >= target)
                r = mid;
            else 
                l = mid+1;
        }
        if (nums[l] != target) // 不相等意味着没找到target
            return {-1,-1};
        else 
        {
            int ll = 0, rr = nums.size()-1;
            while (ll<rr) { //循环结束ll==rr,此时ll或者rr的值即为右边界
                int mid = (ll+rr+1) >> 1;
                if (nums[mid] <= target)
                    ll = mid;

                else 
                    rr =mid -1;
            }
            return {l,ll};
        }
    }
};

 

// 左边界
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (nums[mid] >= target) r = mid;   //左边界,所以r=mid,此时【l,r】一定包含了左边界 
        else l = mid + 1;
    }
    return l;
}
// 右边界
// 区间[l, r]被划分成[l, mid-1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;   //这里需要加1,使得mid取靠右的值,
        // 比如【1,2】,l = 1 r = 2, mid = 2; 
        if (nums[mid] <= target) l = mid;  // 右边界,l=mid,此时【l,r】一定包含了右边界 
        else r = mid - 1;
    }
    return l;
}

刚开始利用方法2写代码时,报错runtime error: reference binding to null pointer of type ‘int‘ (stl_vector.h)。

debug很久,没找到原因。后来用方法1运行通过,再尝试方法2,又可以提交通过。大冤种就是我了!

写一遍博客简单记录一下,如有帮助,可以点赞收藏一波哈哈哈哈~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值