需求:
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target,返回 [-1, -1]。 示例: 输入:nums = [5,7,7,8,8,10], target = 8 输出:[3,4]
思路
1.有四种情况:
情况一:数组为空
情况二:数组中不存在target
情况三:target在有序数组的范围外
情况四:正常
2.通过左右索引(l、r)查找左边界和右边界。
3.l左边的数都小于target,右边的数都大于等于target。所以通过>=条件来随时移动r(r = mid),循环判断左右索引的大小。右边界同样。
代码
public int[] searchRange(int[] nums, int target) {
int n = nums.length;
if(n == 0) {//情况1
return new int[]{-1,-1};
}
int l = 0, r = n - 1;
//找左边界
while (l < r) {
int mid = (l + r) / 2;
if (nums[mid] >= target) {
r = mid;
} else {
l = mid + 1;
}
}//此时,l指向第一个值
if (nums[l] != target) {//情况2、3
return new int[]{-1, -1};
}
int k = l;//存放左指针
r = n - 1;
//找右边界
while (l < r) {
int mid = (l + r + 1) / 2;//必须加1,防止死循环
if (nums[mid] <= target) {
l = mid;
} else {
r = mid - 1;
}
}
return new int[]{k,r};
}
注意
1.循环时尤其注意“+1”,需不需要“+1”非常重要,必须想清楚。
2.在判断时,“=”意味着继续移动,直到外部大循环结束,此时边界刚好指向第一个配对的值。
3.int mid = (l + r + 1) / 2 这里如果没有+1,会直接造成死循环,
比如[5,7,7,8,8,10]查找8时,会出现移动前“(3+5)/2=4”和移动后“(4+5)/2=4”值相等的情况。
(leetcode.34)