素体:
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
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;
}
}
return -1;
}
变种
public int[] searchRange(int[] nums, int target)
{
int[] ret = new int[2];
ret[0] = ret[1] = -1;
// 处理边界情况
if(nums.length == 0) return ret;
// 1. ⼆分左端点
int left = 0, right = nums.length - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
if(nums[mid] < target) left = mid + 1;
else right = mid;
}
// 判断是否有结果
if(nums[left] != target) return ret;
else ret[0] = right;
// 2. ⼆分右端点
left = 0; right = nums.length - 1;
while(left < right)
{
int mid = left + (right - left + 1) / 2;
if(nums[mid] <= target) left = mid;
else right = mid - 1;
}
ret[1] = left;
return ret;
}
分析
index
左右两次数据的特点:
▪
[0, index-1]
之间的元素,都是⼩于
x
的;
▪
[index , x]
之间的元素,都是⼤于 等于
x
的。
//寻找左边界(从左到右第一个大于等于target)
while (start < end) {
int mid = start + (end - start) / 2;
if (nums[mid] >= target) {
end = mid;
} else if (nums[mid] < target) {
start = mid + 1;
}
}
分析
index
左右两次数据的特点:
▪
[0, index]
之间的元素,都是⼩于等于
x
的;
▪
[index + 1, x]
之间的元素,都是⼤于
x
的。
//寻找右边界(从左到右最后一个小于等于target)
start = 0;
end = nums.length - 1;
while (start < end) {
int mid = start + (end - start + 1) / 2;
if (nums[mid] <= target) {
start = mid;
} else if (nums[mid] > target) {
end = mid - 1;
}
}