地址:https://leetcode-cn.com/problems/binary-search/
原始二分查找实现:循环
Java 代码:
public class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return -1;
}
// 在 [left, right] 区间里查找 target
int left = 0;
int right = len - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
// 下一轮搜索区间:[left, mid - 1]
right = mid - 1;
} else {
// 此时:nums[mid] < target
// 下一轮搜索区间:[mid + 1, right]
left = mid + 1;
}
}
return -1;
}
}
原始二分查找实现:递归
Java 代码:
public class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return -1;
}
return binarySearch(nums, target, 0, len - 1);
}
/**
* 在数组 arr 的子区间 [left, right] 里搜索目标元素
*
* @param arr 数组
* @param target 目标元素
* @param left 左边界索引,包括 left
* @param right 右边界索引,包括 right
* @return
*/
private int binarySearch(int[] arr, int target, int left, int right) {
// 先处理递归到底的情况
if (left > right) {
// 不能形成区间,返回 -1 表示没有找到
return -1;
}
int mid = (left + right) / 2;
if (target == arr[mid]) {
// 找到了,就将目标元素的索引返回
return mid;
} else if (target < arr[mid]) {
// 既然是有序数组,目标元素的值比中间元素还要小,就应该在中间元素的左边去找
return binarySearch(arr, target, left, mid - 1);
} else {
// 既然是有序数组,目标元素的值比中间元素还要大,就应该在中间元素的右边去找
return binarySearch(arr, target, mid + 1, right);
}
}
}
“减治法”二分查找
把等于元素放在最后判断的二分查找算法。
注意:看到 left = mid;
取中间数的时候要加 1
。
- 实现 1:
Java 代码:
public class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len - 1;
while (left < right) {
// 注意:根据分支逻辑,需要在取中间数的时候,向上取整
int mid = (left + right + 1) >>> 1;
if (nums[mid] > target) {
// 下一轮搜索区间是:[left, mid - 1]
right = mid - 1;
} else {
// 此时 nums[mid] <= target
// mid 的左边一定不等于目标元素
// 下一轮搜索区间是:[mid, right]
left = mid;
}
}
// 不要忘了单独做判断
if (nums[left] == target) {
return left;
}
return -1;
}
}
- 实现 2:
Java 代码:
public class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len - 1;
while (left < right) {
int mid = (left + right) >>> 1;
if (nums[mid] < target) {
// 下一轮搜索区间是:[mid + 1, right]
left = mid + 1;
} else {
// 此时 nums[mid] >= target,
// mid 的右边一定不存在 target,下一轮搜索区间是:[left, mid]
right = mid;
}
}
// 不要忘了单独做判断
if (nums[left] == target) {
return left;
}
return -1;
}
}