题目描述:
题目: 给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
要求:
- 你的算法时间复杂度必须是 O(log n) 级别。
- 如果数组中不存在目标值,返回 [-1, -1]。
思路分析:
要求时间复杂度为logn,可以考虑用二分查找来解决问题。
参考代码:
public int[] searchRange(int[] nums, int target) {
if(nums == null || nums.length == 0)return new int[]{-1,-1};
int start = first(nums, target);
int end = last(nums, target);
return new int[]{start, end};
}
//找到第一个位置
public int first(int[] nums, int target){
int lower = 0;
int high = nums.length - 1;//1.这里注意
while(lower <= high){//1处length-1,则这里就是 <=
int mid = lower + (high - lower) / 2;
if(target > nums[mid])lower = mid + 1;
else if(target < nums[mid])high = mid - 1;
else high = mid - 1;//注意:等于时,high左移
}
if(lower >= nums.length || nums[lower] != target)return -1;//注意这里的写法
return lower;
}
//找到最后一个位置
public int last(int nums[], int target){
int lower = 0;
int high = nums.length - 1;//1.这里注意
while(lower <= high){//1处length-1,则这里就是 <=
int mid = lower + (high - lower) / 2;
if(target > nums[mid])lower = mid + 1;
else if(target < nums[mid])high = mid - 1;
else lower = mid + 1;//注意:等于时,lower右移
}
if(high< 0 || nums[high] != target)return -1;//注意这里的写法
return high;
}
小结:
关于二分查找的注意事项:
- high = length 还是 high = length - 1;不同的方式while中有不同的写法;
- while(lower < high) 还是while(lower <= high);
- 查找元素最后出现的位置时,if(target == nums[mid]) 时,left = mid;还是left = mid + 1;
- 查找元素首次出现的位置时,if(target == nums[mid]) 时,right = mid;还是right = mid - 1;
- while循环结束最后的判断语句的写法。
要弄懂上面问题和二分查找其他的注意事项,强力推荐二分法查找的详细细节。
(完)