前面我们通过一系列分享,相信你已经掌握了常用的排序算法思想和代码实现,你还记得它们吗?让我们一起来简单回顾一下:冒泡排序、插入排序、选择排序、归并排序、快速排序、桶排序、计数排序。我们一共分享了七个常见的排序算法。
接下来我们通过两篇文章分享一个以排序为基础的算法:二分查找。二分查找是一个高效的查找算法,它的时间复杂度是:O(logn) 。那具体什么是二分查找呢?
让我们一起来玩一个游戏,通过游戏,相信你很快就能理解二分查找了:
1.今天正好是周末,你们几个朋友在家没有什么事做,有人提议玩猜字游戏
2.具体游戏规则是这样的:
- 从0-49个数字中,任意选择一个目标数字,比如:9
- 当然目标数字,在答案揭晓前,是需要隐藏起来的(只能你看见,不能让你的朋友看见)
- 然后你的朋友开始猜字,每次猜测,你只需要告诉朋友:比目标数字大了,或者小了,或者猜中了(揭晓答案)
3.问题:
- 你的朋友要如何猜测,能在最短的时间内,猜中目标数字?
#考考你:
1.你知道二分查找的核心思想吗?
2.你能用java实现二分查找吗?
案例
二分查找核心思想
我们还是以上面的猜字游戏为基础,来分析二分查找的核心思想。游戏背景是:
1.有0-49个数字,任意从中选择一个数字,作为目标数字,比如:9
2.如何在最短的时间内,猜中目标数字:9
二分查找核心思想:
1.第一次,选择0-49范围内的中间数字,比如(0+49)/2=24
2.将中间数字24,与目标数字9比较,得出:24>9
3.第二次,将数据查找范围减半,由于第一次的24>9,第二次选择:0-23的范围
4.选择0-23范围内的中间数字,比如:(0+23)/2=11
5.将中间数字11,与目标数字9进行比较,得出:11>9
6.以此类推,每次将数据范围减半(折半查找==二分查找).......
7.分析到这里,你应该已经理解了二分查找的核心思想:每一次将数据范围减半,查找目标数字,能够在最短的时间内,找到目标数字
二分查找代码实现
循环实现
package com.anan.algorithm.search;
import java.util.Arrays;
/**
* 二分查找,循环实现
*/
public class BinarySearchWhile {
public static void main(String[] args) {
// 排好序的数组(二分查找的前提)
int[] array = {1,3,5,7,9,10,12,14,16,17,18,19};
// 目标值
int target = 9;
System.out.println("1.有序数组:"+ Arrays.toString(array));
System.out.println("2.查找目标数字:" + target);
// 开始二分查找
System.out.println("-------------------------开始二分查找------------------------");
int index = binarySearch(array,array.length,target);
System.out.println("3.查找目标值:" + target + ",在数组中的下标索引:" + index);
}
/**
* 二分查找
* @param array 数据集合(数组)
* @param n 数据规模
* @return
*/
public static int binarySearch(int[] array,int n,int target){
int result = -1;
// 定义下标标记索引
int low = 0;
int high = n - 1;
while (low <= high){
int mid = (low + high) / 2;
if(array[mid] == target){
return mid;
}else if(array[mid] < target){
low = mid + 1;
}else {
high = mid - 1;
}
}
return result;
}
}
递归实现
package com.anan.algorithm.search;
import java.util.Arrays;
/**
* 二分查找,递归实现
*/
public class BinarySearchRecursion {
public static void main(String[] args) {
// 排好序的数组(二分查找的前提)
int[] array = {1,3,5,7,9,10,12,14,16,17,18,19};
// 目标值
int target = 9;
System.out.println("1.有序数组:"+ Arrays.toString(array));
System.out.println("2.查找目标数字:" + target);
// 开始二分查找
System.out.println("-------------------------开始二分查找------------------------");
int index = binarySearch(array,array.length,target);
System.out.println("3.查找目标值:" + target + ",在数组中的下标索引:" + index);
}
/**
* 二分查找入口(递归实现)
*/
public static int binarySearch(int[] array,int n,int target){
return recursionBinarySearch(array,0,n - 1,target);
}
/**
* 二分查找递归
* @param array 目标数组
* @param low 查找范围低位
* @param high 查找范围高位
* @param target 目标值
* @return
*/
public static int recursionBinarySearch(int[] array,int low,int high,int target){
// 递归终止条件
if(low > high){
return -1;
}
// 计算中位数
int mid = low + ((high - low) >>1);
if(array[mid] == target){
return mid;
}else if(array[mid] < target){
return recursionBinarySearch(array,mid + 1,high,target);
}else{
return recursionBinarySearch(array,low, mid - 1,target);
}
}
}
讨论分享
#考考你答案:
1.你知道二分查找的核心思想吗?
二分查找核心思想
2.你能用java实现二分查找吗?
二分查找代码实现
3.思考题:
1.二分查找的代码实现比较简单,很容易理解
2.请你先思考:二分查找的代码实现,需要注意的细节事项
3.请你先思考:如果目标数组中,有重复的数字,二分查找该如何实现呢?
【以上思考问题】:我们将在下一篇分享中讨论