青铜挑战:逢试必考的二分查找
1.什么是二分查找?
二分查找就是将数组的中间值和目标值比较,然后排除掉数组一半的元素,在另一半中继续利用中间值和该目标值进行比较,依次类推;前提是给定的数组要有序
对于在一个有序的数组中找出目标值的问题,我们应该要很快想到使用二分查找来解决;
2.如何实现二分查找算法呢?
/*
* 使用循环方式来实现
* */
public static int binarySearchByCirculation(int[] arr, int low, int high, int target) {
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (arr[mid] == target) {
return mid;
} else if (arr[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
// 没有找到
return -1;
}
/*
* 利用递归方式来实现
* */
public static int binarySearchByRecursion(int[] arr, int low, int high, int target) {
if (low <= high) {
int mid = low + ((high - low) >> 1);
if (arr[mid] == target) {
return mid;
} else if (arr[mid] > target) {
return binarySearchByRecursion(arr, low, mid - 1, target);
} else {
return binarySearchByRecursion(arr, mid + 1, high, target);
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {1, 2, 4, 6, 8, 9};
int target = 1;
int res1 = binarySearchByCirculation(arr, 0, arr.length - 1, target);
int res2 = binarySearchByRecursion(arr, 0, arr.length - 1, target);
System.out.println(res1 == res2); // 输出true
}
3.二分查找重复元素最左侧元素的下标
解题思路:首先利用二分查找定位到目标值的位置mid,再依次从mid位置向左开始寻找,直到元素不重复为止;
具体实现:
public static int binarySearchLeftEle(int[] arr, int left, int right, int target) {
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (arr[mid] > target) {
right = mid - 1;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
// 一直向左寻找直到元素不再重复
while (mid > 0 && arr[mid] == target) mid--;
// 如果此时mid == 0 并且还是重复元素,直接返回mid即可,也就是0;
if (mid == 0 && arr[mid] == target) {
return mid;
}
// 表示发现了往左寻找的第一个不重复元素,那么mid向右的一个位置即是重复元素中最左位置;
return mid + 1;
}
}
return -1;
}