这道题一开始百思不得其解,看了好几种和好多遍解答。终于领悟精髓。
题目如图:
拿到题目粗略分析思路
- 时间复杂度=>二分查找法
- 用两个二分查找法分别定位开始和结束位置
- 查找结果可能性分析
具体分析思路(自底部而上逐层分析)
1.查找结果可能性分析(同时确定二分查找法区间是 左闭右开 还是 左闭右闭)
选择 左闭右开
结果分析(定义-1 为未能查找到的结果):
- 目标值不在数组中 返回(-1,-1)
- 目标值在数组中 返回(左边界,右边界-1)
此步骤完成代码如下:
vector<int> searchRange(vector<int>& nums, int target) {
int leftBoard = searchLeftBoard(nums,target);
int rightBoard = searchRightBoard(nums,target);
if(-1 == leftBoard || -1 == rightBoard)
{return{-1,-1};}
else {return {leftBoard,rightBoard-1};}
}
2.写左右边界查找算法(以左边界 为例)
1.写出二分查找法基本架构(左闭右闭)(基本功闭着眼都应该能写出来)
int searchLeftBoard(vector<int>& nums, int target){
int l = 0;
int r = nums.size();
while( l < r){
int mid = (r - l )/2 + l;
if( target > nums[mid]){
l = mid + 1;
}else if(target == nums[mid]){
//暂且空着
}else{
r = mid;
}
}
return ;//暂且空着
}
2.添加一个左边界变量 初始为-1,返回结果为-1,表明未查找到结果
int searchLeftBoard(vector<int>& nums, int target){
int l = 0;
int r = nums.size();
int leftBoard = -1;//添加
while( l < r){
int mid = (r - l )/2 + l;
if( target > nums[mid]){
l = mid + 1;
}else if(target == nums[mid]){
//暂且空着
}else{
r = mid;
}
}
return leftBoard ;//添加
}
3.返回边界值
在判断 target 和 nums[mid]相等时 更新 l 或 r 并 返回边界值。
- 确立边界:r = mid 如果是确定右边界 应该是 l = mid + 1;
- 返回边界值 : leftBoard = r 这里会有很多人疑问 为啥不是 用 l 赋值 原因是:这里的 l 和 r 是左边界的 l 和 r 。每次 target 和 nums[mid] 相等时,都会更新边界值,即将 l 和 r 赋值给边界值。
该部分代码如下:
int searchLeftBoard(vector<int>& nums, int target){
int l = 0;
int r = nums.size();
int leftBoard = -1;
while( l < r){
int mid = (r - l )/2 + l;
if( target > nums[mid]){
l = mid + 1;
}else if(target == nums[mid]){
r = mid;
leftBoard = r;
}else{
r = mid;
}
}
return leftBoard;
}
整体代码如下:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int leftBoard = searchLeftBoard(nums,target);
int rightBoard = searchRightBoard(nums,target);
if(-1 == leftBoard || -1 == rightBoard)
{return{-1,-1};}
else {return {leftBoard,rightBoard-1};}
}
int searchLeftBoard(vector<int>& nums, int target){
int l = 0;
int r = nums.size();
int leftBoard = -1;
while( l < r){
int mid = (r - l )/2 + l;
if( target > nums[mid]){
l = mid + 1;
}else if(target == nums[mid]){
r = mid;
leftBoard = r;
}else{
r = mid;
}
}
return leftBoard;
}
int searchRightBoard(vector<int>& nums, int target){
int l = 0;
int r = nums.size();
int rightBoard = -1;
while( l < r){
int mid = (r - l )/2 + l;
if( target < nums[mid]){
r = mid ;
rightBoard = l;
}else if(target == nums[mid]){
l = mid + 1;
rightBoard = l;
}else{
l = mid + 1;
}
}
return rightBoard;
}
};