题目
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
解题思维
- 根据时间复杂度来看,可能要用到折半查找。
- 总之先写个最普通的折半查找
public static int[] searchRange(int[] nums, int target) {
//定义最小 最大的索引
int start=0;
int end=nums.length-1;
//返回最后答案的数组
int[] ans = {-1,-1};
//判断条件就用start和end比较
while (start<=end){
int par = (start+end)/2;
if(nums[par]>target) end=par-1;
else if(nums[par]<target) start=par+1;
else{
ans[0]=par;
ans[1]=par;
break;
}
}
if(ans[0]==-1) return ans;
return ans;
}
然后我想用折半查找继续找开头和结尾,结果完全写不出来,于是采用最简单的向左向右遍历吧两个if语句是针对特殊情况
//向左向右找
for(int i=ans[0];i>=0;i--){
if(nums[i]!=target){
ans[0]=++i;
break;
}
}
if(nums[0]==target) ans[0]=0;
for(int i=ans[0];i<=nums.length-1;i++){
if(nums[i]!=target){
ans[1]=--i;
break;
}
}
if(nums[nums.length-1]==target) ans[1]=nums.length-1;
- 还有种特殊情况是长度为1
//如果长度为1 那么start会等于end 这时候直接判断就行
if(start==end){
if(nums[0]!=target) return ans;
else {
ans[0]=0;
ans[1]=0;
return ans;
}
}
最终代码
public static int[] searchRange(int[] nums, int target) {
//定义最小 最大的索引
int start=0;
int end=nums.length-1;
//返回最后答案的数组
int[] ans = {-1,-1};
//如果长度为1 那么start会等于end 这时候直接判断就行
if(start==end){
if(nums[0]!=target) return ans;
else {
ans[0]=0;
ans[1]=0;
return ans;
}
}
//判断条件就用start和end比较
while (start<=end){
int par = (start+end)/2;
if(nums[par]>target) end=par-1;
else if(nums[par]<target) start=par+1;
else{
ans[0]=par;
ans[1]=par;
break;
}
}
if(ans[0]==-1) return ans;
//向左向右找
for(int i=ans[0];i>=0;i--){
if(nums[i]!=target){
ans[0]=++i;
break;
}
}
if(nums[0]==target) ans[0]=0;
for(int i=ans[0];i<=nums.length-1;i++){
if(nums[i]!=target){
ans[1]=--i;
break;
}
}
if(nums[nums.length-1]==target) ans[1]=nums.length-1;
return ans;
}