1、题目:在排序数组中查找元素的第一个和最后一个位置
注意事项:
当考虑查找元素的边界如0(数组没有元素),代码块需要判断length-1合法可以利用这个下标取出数组中的值,当数组为空时,会出现数组溢出的情况。 在计算数组中间值的时候,为了防止数组溢出 使用的是middle = left + ((right - left) >> 1),使用>>表示右移 比% /的效率高。
方法一
这道题先使用传统的二分算法 查找中间的middle值,有两种可能:
第一种是找到了,那么接下来从中间开始查找左右区间,从middle往前或者往后移动(使用两个变量可以使用之前使用的两个left和right变量)但是这里因为移动变量后续通过变量取数组中的数值,所以需要考虑变量溢出的情况,即left和right和0和length-1的关系,如果溢出则break 第二种没有找到 则返回[-1,-1] 代码如下:
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = {-1, -1};
if(nums.length==0 || target < nums[0] ||target > nums[nums.length - 1] ){
return result;
}
int left = 0;
int right = nums.length - 1;
int middle = 0;
while(left <= right){
middle = left + ((right - left) >> 1);
if(nums[middle] > target){
right = middle - 1;
}else if(nums[middle] < target){
left = middle + 1;
}else{
break;
}
}
if(left > right){
return result;
}
left = middle;
right = middle;
while(nums[left] == target){
left -= 1;
if(left < 0 ){
break;
}
}
while(nums[right] == target){
right += 1;
if(right > nums.length - 1){
break;
}
}
result[0] = left + 1;
result[1] = right - 1;
return result;
}
}
方法二
首先需要先考虑3种情况:
第一种,即不存在目标元素:目标元素不存在数组中(这里利用找到的边界的差等于1 进行排除) 第二种,即目标元素在其中(通过找到的边界差大于1 进行获取) 第三种 数组里面元素为空;目标元素和下标边界的直接对比小于0,大于length-1 :通过未赋值的边界进行处理[-2, -2] 根据以上三种情况,写算法,如何确定上下边界呢?通过修改二分查找中的相等条件,使用left确定上边界,即相等的时候移动left;使用right确定下边界,即相等的时候移动right。
这里考虑了特殊情况,当目标元素小于nums[0]时,当确定上边界时,需要移动left,而left移动的条件是target更大,所以不可能被赋值,同理目标元素大于nums[nums.length-1]时,确定下边界,需要更新right,而right的值更新是小于某个值,所以下边界不能被确认。
区分情况一和情况二,通过赋值之后的元素差进行区分,如果相差为1,则说明不存在目标元素,反之则存在。
因为下边界是找到目标数组中第一小于目标元素的值(小于目标元素的最大值),同理上界也是,所以可以通过下标确定元素是否存在,不存在,则小边界和上边界连续。