前言
你好, 我是Cici。我一直觉得自己的算法是短板,所以打算自己重新系统的刷一刷,谈谈自己的思路,说说自己的思考,加强自己的同时也希望能给大家带来帮助。其实数据结构和算法属于我们技术人员的内功,不管技术怎么更新,它始终都是不变的。
同类题目推荐:
一、问题描述
观察题目,我们可以得到的关键信息有:
nums是一个非递减数组- 要求的时间复杂度为
O(log n) - 要找到两个值:开始位置 和 结束位置
二、题目分析
由关键信息,我们首先考虑使用二分查找法来解决问题
分析题目,最终的结果有三种情况:
- target 在数组范围中且数组中不存在 target,例如 nums = [5, 7, 8, 10],target = 6,此时返回 [-1, -1]。
- target 在数组范围中且数组中存在 target,例如 nums = [5, 7, 8, 10],target = 8,此时返回 [2,2]。
- target 不在数组范围中,在数组的左右两侧,例如 nums = [5, 7, 8, 10],target = 4 或者 target = 11,此时返回 [-1, -1]。
解题思路:
- 第一次二分查找,寻找 target 的左边界
- 第二次二分查找,寻找 target 的右边界
- 根据这两次查找的结果,结合上面分析的三种情况,返回最终结果。
三、参考代码
class Solution {
public int[] searchRange(int[] nums, int target) {
int left = findLeft(nums, target);
int right = findRight(nums, target);
// 三种情况
if(left == -2 || right == -2){
return new int[]{-1, -1};
}
if(right - left > 1){
return new int[]{left + 1, right - 1};
}
return new int[]{-1, -1};
}
public int findLeft(int[] nums, int target){ //寻找左边界
int left = 0;
int right = nums.length - 1;
int temp = -2; //辅助值,用于返回结果
while(left <= right){
int mid = left + (right - left) / 2;
if(nums[mid] >= target){
right = mid - 1;
temp = right;
}else{
left = mid + 1;
}
}
return temp;
}
public int findRight(int[] nums, int target){ //寻找右边界
int left = 0;
int right = nums.length - 1;
int temp = -2;
while(left <= right){
int mid = left + (right - left) / 2;
if(nums[mid] <= target){
left = mid + 1;
temp = left;
}else{
right = mid - 1;
}
}
return temp;
}
}