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 <= nums[i] <= 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;
    }
};
相关推荐
W23035765731 小时前
经典算法:最长上升子序列(LIS)深度解析 C++ 实现
开发语言·c++·算法
.Ashy.1 小时前
2026.4.11 蓝桥杯软件类C/C++ G组山东省赛 小记
c语言·c++·蓝桥杯
2401_892070981 小时前
链栈(链式栈) 超详细实现(C 语言 + 逐行精讲)
c语言·数据结构·链栈
minji...2 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法
语戚3 小时前
力扣 968. 监控二叉树 —— 贪心 & 树形 DP 双解法递归 + 非递归全解(Java 实现)
java·算法·leetcode·贪心算法·动态规划·力扣·
skywalker_113 小时前
力扣hot100-7(接雨水),8(无重复字符的最长子串)
算法·leetcode·职场和发展
bIo7lyA8v4 小时前
算法稳定性分析中的输入扰动建模的技术9
算法
CoderCodingNo4 小时前
【GESP】C++三级真题 luogu-B4499, [GESP202603 三级] 二进制回文串
数据结构·c++·算法
sinat_286945194 小时前
AI Coding 时代的 TDD:从理念到工程落地
人工智能·深度学习·算法·tdd