0、前言
二分查找是从一个有序的数组中找到目标值,分为两种类型:找到一个目标值、找到目标值的边界。
1、从有序数组中找到目标值
首先让数组有序,这是二分查找的前提。
int findTarget(int *nums, int numsSize, int target)
{
int left = 0;
int right = numsSize - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
}
}
return -1;
}
2、从有序数组中找到目标值的边界
这种适合存在多个目标值的情况,找到左右边界。
2.1 左边界查找
int findLeft(int *nums, int numsSize, int target)
{
int left = 0;
int right = numsSize - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
}
}
if (left > numsSize - 1 || nums[left] != target) {
return -1;
}
return left;
}
查找的过程:left 往右走,right 往左走。
当循环结束后,有“找到”和“没找到”两种情况。找到的情况很简单,直接 left 就是结果。
没找到的情况一:目标值比数组最大值还大,left 跑出了边界,判断方法为left > numsSize - 1
;
没找到的情况二:目标值比数组最小值还小,left 没动,此时和 nums[0] 恰好为左边界的结果一样,因此不能拿 left == 0
作为判断条件,而是 nums[left] != target
;
2.2 右边界查找
int findRight(int *nums, int numsSize, int target)
{
int left = 0;
int right = numsSize - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
left = mid + 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
}
}
if (right < 0 || nums[right] != target) {
return -1;
}
return right;
}
查找的过程:left 往右走,right 往左走。
当循环结束后,有“找到”和“没找到”两种情况。找到的情况很简单,直接 right 就是结果。
没找到的情况一:目标值比数组最小值还小,right 跑出了边界,判断方法为right < 0
;
没找到的情况二:目标值比数组最大值还大,right 没动,此时和 nums[numsSize - 1]
恰好为右边界的结果一样,因此不能拿 right == numsSize - 1
作为判断条件,而是 nums[right] != target
;