34.在排序数组中查找元素的第一个和最后一个位置(力扣LeetCode)

文章目录

34.在排序数组中查找元素的第一个和最后一个位置

题目描述

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

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

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

示例 1:

输入:nums = 5,7,7,8,8,10, target = 8

输出:3,4

示例 2:

输入:nums = 5,7,7,8,8,10, target = 6

输出:-1,-1

示例 3:

输入:nums = \[\], target = 0

输出:-1,-1

提示:

  • 0 <= nums.length <= 105
  • -109 <= numsi <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

二分

  这里有个坑,一个数组和vertor的坑,因为我平时习惯用数组,不会在意二分查找如果找不到的一个边界问题(数组开全局变量,初始化为零,并且我数组会开的很大,不会越界),但使用vector时一旦找不到会存在vector的访问越界

  • 以前使用数组时直接if(b[l] == a) return l;
cpp 复制代码
int find1(int a)
{
    int l = 0, r = n - 1;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(b[mid] >= a) r = mid;
        else l = mid + 1;
    }
    if(b[l] == a) return l;
    return -1;
}
  • 现在使用vector需要判断是否越界if (r < 0) return -1;
cpp 复制代码
int find1(vector<int>& nums, int n)
    {
        int l=0,r=nums.size()-1;
        while(l<r)
        {
            int mid=l+r>>1;
            if(nums[mid]>=n) r=mid;
            else             l=mid+1;
        }
        if (r < 0) return -1;
        if (nums[r] == n) return r;
        return -1;
    }
cpp 复制代码
// 定义解决问题的类 Solution
class Solution {
public:
    // 主函数,用来查找目标值的开始和结束位置
    vector<int> searchRange(vector<int>& nums, int target) {
        // 初始化结果数组为 [-1, -1],表示目标值的开始和结束位置
        vector<int> num(2, -1);
        // 首先查找目标值的开始位置
        num[0] = find1(nums, target);
        // 如果开始位置为 -1,说明数组中没有目标值,直接返回 [-1, -1]
        if(num[0] == -1) return num;
        // 否则,查找目标值的结束位置
        else num[1] = find2(nums, target);
        // 返回包含开始和结束位置的数组
        return num;
    }

private:
    // 辅助函数 find1,用于查找目标值的开始位置
    int find1(vector<int>& nums, int n) {
        // 初始化二分查找的左右边界
        int l = 0, r = nums.size() - 1;
        while(l < r) {
            // 查找左中位数,因为我们在查找开始位置
            int mid = (l + r) >> 1;
            // 如果中间值大于等于目标值 n,我们将右边界移动到 mid
            if(nums[mid] >= n) r = mid;
            // 否则,将左边界移动到 mid + 1
            else l = mid + 1;
        }
        // 检查边界条件,确保 r 没有越界
        // 查找左边界时,r会一直逼近左边界,如果找不到r<0
        if (r < 0) return -1;
        // 如果 nums[r] 等于目标值 n,则 r 是开始位置
        if (nums[r] == n) return r;
        // 否则,说明数组中没有目标值,返回 -1
        return -1;
    }

    // 辅助函数 find2,用于查找目标值的结束位置
    int find2(vector<int>& nums, int n) {
        // 初始化二分查找的左右边界
        int l = 0, r = nums.size() - 1;
        while(l < r) {
            // 查找右中位数,因为我们在查找结束位置
            int mid = (l + r + 1) >> 1;
            // 如果中间值小于等于目标值 n,我们将左边界移动到 mid
            if(nums[mid] <= n) l = mid;
            // 否则,将右边界移动到 mid - 1
            else r = mid - 1;
        }
        // 检查边界条件,确保 l 没有越界
        // 查找右边界时,l会一直逼近右边界,如果找不到l>nums.size()-1(l >= nums.size())
        if (l >= nums.size()) return -1;
        // 如果 nums[l] 等于目标值 n,则 l 是结束位置
        if (nums[l] == n) return l;
        // 否则,说明数组中没有目标值,返回 -1
        return -1;
    }
};
相关推荐
2601_9561219737 分钟前
背包基础篇(01、完全、分组、多重、混合)
c++·算法·动态规划
fpcc1 小时前
跟我学C++中级篇——编译期的条件选择
开发语言·c++
兴通物联科技2 小时前
SMT PCB 微小 DataMatrix 码扫不动问题分析 兴通 XT8601B 600 万像素工业读码器落地实践
大数据·人工智能·单片机·嵌入式硬件·算法·计算机视觉
月华路4 小时前
G1 GC 对数组与大对象(Humongous)的处理
java·jvm·算法
我想走路带风4 小时前
LRU和最长前缀和(计算机网络算法)
计算机网络·算法
M78佐菲5 小时前
Linux学习笔记:进程
linux·笔记·学习·算法
ShineWinsu5 小时前
对于C++:C++20中线程、初始化、Lambda与内存视图等特性的解析
c++·c++20
徐小夕6 小时前
表格、文档、甘特、大屏、表单一站打通:pxcharts超级表格4.0正式上线!
前端·算法·github
Xin7706 小时前
LeetCode 23.合并 K 个升序链表(分治递归)
leetcode