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 <= 10^5^
  • -10^9^ <= nums[i] <= 10^9^
  • nums 是一个非递减数组
  • -10^9^ <= target <= 10^9^

二分

这里有个坑,一个数组和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;
    }
};
相关推荐
BingLin-Liu34 分钟前
蓝桥杯备考:数据结构之栈 和 stack
数据结构
就叫飞六吧1 小时前
51 单片机和 STM32 引脚命名对照表与解析
c++·stm32·单片机·嵌入式硬件·51单片机
霜雪殇璃1 小时前
c++对结构体的扩充以及类的介绍
开发语言·c++·笔记·学习
冉佳驹1 小时前
C++ ——— 匿名对象
c++·学习·类和对象·匿名对象
Luo_LA1 小时前
【LeetCode Hot100 贪心算法】 买卖股票的最佳时机、跳跃游戏、划分字母区间
leetcode·游戏·贪心算法
誓约酱2 小时前
git的基本使用
linux·运维·服务器·c++·git·后端
范纹杉想快点毕业2 小时前
XML通过HTTP POST 请求发送到指定的 API 地址,进行数据回传
xml·c语言·开发语言·数据结构·c++·python·c#
星迹日2 小时前
数据结构:LinkedList与链表—无头单向链表(一)
java·数据结构·经验分享·笔记·链表·单向链表
float_六七2 小时前
C/C++头文件locale
c语言·开发语言·c++
OTWOL2 小时前
栈与队列OJ题精选,数据结构的实践应用
数据结构