文章目录
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;
}
};