当当当,算法系列又来了,我们来看一下二分查找。
二分查找
概念
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
趣解
关于二分查找,我们平常生活中经常遇到,果然是万物源于生活呀!
例如年会的时候,我们要搞一个小游戏,猜主持人要发红包的金额,金额在1-1000之间。
这时候展现实力的时候就到了,怎么能快速找到这个数字呢?最快的方法就是利用二分查找了,一半一半的进行缩减数字。
例如:主持人想发红包的金额为666
主持人 | 我 | 次数 |
---|---|---|
小了 | 500 | 1 |
大了 | 750 | 2 |
小了 | 625 | 3 |
大了 | 687 | 4 |
小了 | 656 | 5 |
大了 | 671 | 6 |
小了 | 663 | 7 |
大了 | 667 | 8 |
小了 | 665 | 9 |
对了 | 666 | 10 |
由上可见,10次我们就可以猜出正确的数字了。
非递归实现
我们现在需要实现的是一个有序的数组,找到特定的数字然后返回其下标即可。
拆解步骤
- 首先确定左右两个下标
- 拿出中间坐标的数字和需要查找的数字进行对比
- 如果小于需要查找的数字,左下标就变成中间下标加一,反之右下标就变成中间下标减一。
- 反复查找,直到左下标大于等于右下标或者找到数字为止。
/**
* 查找有序数组中某个数字的下标
*
* @return
*/
private static int findSubscript(int[] n, int num) {
// 1. 首先确定左右两个下标
int left = 0;
int right = n.length - 1;
// 3. 左下标小于等于右下标结束循环
while (left <= right) {
// 2. 拿出中间坐标的数字
int mid = (left + right) / 2;
// 3. 找到数字
if (n[mid] == num) {
return mid;
} else if (n[mid] > num) {
// 2. 大于需要查找的数字,右下标就变成中间下标减一
right = mid - 1;
} else if (n[mid] < num) {
// 2. 小于需要查找的数字,左下标就变成中间下标加一
left = mid + 1;
}
}
// 未找到符合要求的数字,返回-1
return -1;
}
递归实现
实现起来比较复杂,可以参考一下。
/**
* 查找有序数组中某个数字的下标
*
* @return
*/
private static int findSubscript(int[] n, int num, int left, int right) {
// 2. 拿出中间坐标的数字
int mid = (left + right) / 2;
// 3. 找到数字
if (n[mid] == num) {
return mid;
} else if (n[mid] > num) {
// 2. 大于需要查找的数字,右下标就变成中间下标减一
return findSubscript(n, num, left, mid - 1);
} else if (n[mid] < num) {
// 2. 小于需要查找的数字,左下标就变成中间下标加一
return findSubscript(n, num, mid + 1, right);
}
// 未找到符合要求的数字,返回-1
return -1;
}
private static int recursive(int[] n, int num) {
// 1. 首先确定左右两个下标
int left = 0;
int right = n.length - 1;
return findSubscript(n, num, left, right);
}
先写这些,后续如果有进阶版会在该文章后面进行新增的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。