题目
给定一个按照升序排列的整数数组 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]
大体思路
这个题目一看到在有序数组中查元素和log(n)就能想到二分查找,我们先来看一下最基本的二分查找是什么。
二分查找一般用于在一个有序线性表中查找元素(元素必须能够直接访问),时间复杂度是log(n),怎么算的我还真不知道。二分查找采用两个指针,分别表示待查找元素的开头索引和结尾索引。如:
而这道题不仅要求我们查找某元素还要求查找这个元素的开头与结尾,所以对二分查找进行改进,我们找到某元素时,不直接break,而是令right=mid-1(这个用于查找最靠前的元素)或者left=mid+1(这个用于查找最靠后的元素)。
基本二分查找模板
//target是目标元素,left right分别是左右指针
while(left<right){
int mid=left+(right-left)/2;
if(nums[mid]==target){
return mid;
}else if(nums[mid]>target){
right=mid-1;
}else if(nums[mid]<target){
left=mid+1;
}
}
提交代码
public class problem34 {
public int[] searchRange(int[] nums, int target) {
int[] targets={-1,-1};
targets[0]=binarySearch(nums, target, true);
targets[1]=binarySearch(nums, target, false);
return targets;
}
public int binarySearch(int[] nums,int target,boolean findleft){
int left=0;
int right=nums.length-1;
int index=-1;
//二分查找
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==target){
index=mid;
//以下的if-else属于对二分查找的更改
if(findleft) right=mid-1;
else left=mid+1;
}else if(nums[mid]>target){
right=mid-1;
}else if(nums[mid]<target){
left=mid+1;
}
}
return index;
}
public static void main(String[] args) {
problem34 pro=new problem34();
int[] nums={5,7,7,8,8,10};
int[] re=pro.searchRange(nums, 6);
System.out.println(re[0]+" "+re[1]);
}
}