Given an array of integers nums
sorted in ascending order, find the starting and ending position of a given target
value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
Example 1:
Input: nums = [5,7,7,8,8,10]
, target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10]
, target = 6
Output: [-1,-1]
这个题目嘛,大部分人肯定和我一样,第一反应绝对是暴力
确实暴力的话这题秒解,时间复杂度也只会是O(n)而已
然而题目要求了O(log n)那肯定要其他做法
很明显O(log n)的话只有二分查找了
一开始我想用递归做的,因为快排也是递归的嘛,后面想了想最后结果是返回2个值,递归的话好像不好搞啊
于是还是循环去搞了
我犯了一个错误,导致我迟迟没解出来
首先肯定知道要分3类,我就分了三类,小于target、大于target和刚好等于target的情况
我错就错在等于target的时候,处理不对,我一开始是以为刚好等于target的时候,只有这个数和相邻的一个数的坐标能返回
后面错了N次后才发现不对
于是就针对刚好等于target一定要有一个解决方法
前面错得太多次了,经过反思,就是我题目意思理解错了
如果是找间隔最远的2个坐标,那向两端找就行了啊!
想通了之后,于是我就很快解出来了
具体方法如下
首先定义一个middle = (left + right) / 2
这个不解释了
从中间开始,如果nums[middle] > target,那么很明显target在middle的左边,所以这时候right = middle - 1;
如果nums[middle] < target,那么left = middle + 1;
最重要的就是如果nums[middle] == target
那么,我们就把left、right都放到middle,也就是left = middle,right = middle;
然后就是从中间往两边搜索了
保证数组不要越界即可
总结来说本题就是先用二分查找法从中间去分治,压缩搜索空间
找到结果后又重新从中间往两边搜索,返回结果
java代码如下:
public int[] searchRange(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int []answer = new int[]{-1,-1};
if(nums.length == 0)
return answer;
if(nums[0] > target || nums[nums.length - 1] < target)
return answer;
while(left <= right){
int middle = (left + right) / 2;
if(nums[middle] < target){
left = middle + 1;
}
if(nums[middle] > target){
right = middle - 1;
}
//找到了之后,从中间向两边找到坐标
if(nums[middle] == target){
left = middle;
right = middle;
while(left != 0 && nums[left - 1] == target){
left--;
}
while(right != nums.length - 1 && nums[right + 1] == target){
right++;
}
answer[0] = left;
answer[1] = right;
break;
}
}
return answer;
}
我也没想到用时会这么短
不过貌似内存耗得很大?