大家好,我是正在学习算法的Ziph!哈哈!我又来啦!
最近也我闲下来的时候看一些算法书籍,去解决一些算法问题。我会将常见的算法以记录的方式放在这里,以供我后续查找,也以这种方式分享给大家!我将把参透的代码做大量注释,尽可能做到每一行代码都简单易懂!
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
要求:
- 必须采用顺序存储结构。
- 必须按关键字大小有序排列。
复杂度分析:O(logN)
什么是二分查找?举例说明(小故事哦!)
小明喜欢小红,于是和小红就表白了。小红这么说:“我们玩个游戏吧,我心里想一个从1 ~ 100的数字并记下来,你如果在10次之内猜到我心里记下的那个数字,我就和你在一起!”。
于是,小明就有一个猜想。
如果开始我猜100的一半也就是50。不管是猜小了还是猜大了,都排除了50个数字。如果猜小了,我下次就继续猜50 ~ 100的中间数,也就是二分数。这样以来,小明利用他的这个猜想猜了几次就猜中了小红心中记起的数字,并获得了小红的芳心。
如果我们遍历这些数字逐个猜的话,那岂不是很麻烦,而且还浪费时间,二分查找就帮小明解决了这个棘手的问题!
那么如果列表中包含40亿个数字,遍历起来可就更麻烦了,而二分查找只需要猜32次就OK!所谓小知识大作为!
不得不说我自己编的这个故事真的很生动形象。(允许我自恋一下哈!)
这就是二分查找,每次猜测的数字的个数以排除的方式呈现出来!如图:(最多7步完成)
手残党也能画图,在线画图工具:https://www.processon.com
OK!懂了二分查找的原理,那么我就直接上代码了!(第一种是原方案,第二种是递归)
/**
* @author Ziph
* @date 2020年3月1日
* @Email [email protected]
* @param key 查找元素
*
* 二分查找
*/
public class TestBinarySearch {
public static void main(String[] args) {
int[] a = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println(binarySearch(a, 5));
}
public static int binarySearch(int array[], int key) {
int mid = array.length / 2;//中间长度的位置
//如果key正好在数组中间的位置返回其位置(数组下标)
if (key == array[mid]) {
return mid;
}
//头部也就是开始的:第一个数组元素,数组下标为0
int head = 0;
//尾部也就是结束的:最后一个数组元素,数组下标为array.length-1
int tail = array.length - 1;
//利用二分查找的特性去循环查找key值
while (head <= tail) {//只要范围没有缩小到只剩下一个元素就继续循环下去
mid = (tail + head) / 2;//每次循环检查中间数组下标mid
if (key < array[mid]) {//猜的数大了
tail = mid - 1;
} else if (key > array[mid]) {//猜的数小了
head = mid + 1;
} else {
return mid;
}
}
return -1;//如果数组中没有key值,则返回-1
}
}
递归的做法
/**
* @author Ziph
* @date 2020年3月1日
* @Email [email protected]
* @param key 查找元素
*
* 二分查找(递归)
*/
public class TestBinarySearch {
public static void main(String[] args) {
int[] a = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println(recursionBinarySearc(a, 0, a.length - 1, 5));
}
public static int recursionBinarySearc(int array[], int head, int tail, int key) {
int mid = (head + tail) / 2;
if (array[mid] == key) {
return mid;
}
if (head >= tail) {//递归出口
return -1;
} else if (key < array[mid]) {
return recursionBinarySearc(array, head, mid - 1, key);
} else if (key > array[mid]) {
return recursionBinarySearc(array, mid + 1, tail, key);
}
return -1;
}
}
结果:当key=5时,返回的都是4(数组下标)