【题目描述】
给你一个按照非递减顺序排列的整数数组 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,又可以提交通过。大冤种就是我了!
写一遍博客简单记录一下,如有帮助,可以点赞收藏一波哈哈哈哈~