引言
今天陪同组长面试一位两年后端经验的开发小哥,开始面试前,看了一下小哥做的笔试题,回答的还可以。之后听了他的自我介绍,以及他对实际项目开发过程的阐述,也是比较清晰,于是可以判断他之前的工作经历是没有问题的。
接着,组长便开始对他进行技术提问,前面回答的都不错,看的出来,在这组长也是比较满意他。但接下来组长问了一个问题:给定一个数组,怎样在数组中寻找特定值?
只见小哥毫不犹豫的说出使用for循环,然后利用if语句来判断后,我心头顿时一紧(小哥的思路)
static int LinearSearch(int[] arr, int x)
{
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == x)
return i;
}
return -1;
}
小哥说完后,组长给了他机会,便又问道:“还有其他解决方式吗?”
显然小哥被组长这么一问,有些懵逼了,便又重新说道:“如果我们知道查找值在数据的位置,我们可以根据索引去获取具体值,毕竟数组有随机访问的特性…等等”
小哥说完后,组长便指引着询问:“你知道过二分查找吗?能讲一下其中原理?”
小哥被这样一问,更加懵逼了,一时不知道怎么回答…
后面小哥的结果我也就不描述了。
说了这么多,只想为大家强调一件事:基础算法很重要!基础算法很重要!基础算法很重要!重要的事情说三遍。
到这里,故事也就结束了,但我们的正题内容才刚刚开始!解下来,我将为大家介绍一下二分查找算法。
如果已经掌握了朋友,看到这里就可以离开了。但我还是希望你能再多看一眼,加深一下记忆也是挺好的。如果没有听说的朋友,那就请仔细学习一下,对你来说,将是百利而无一害,或许在不久的将来你就可能用上。
二分查找(Binary Search)
先来看一下定义:二分查找是一种在有序数组中查找元素的高效算法。它通过不断地将数组分成两半来缩小搜索范围,直到找到所需的元素或搜索范围为空。
注意,这有个极其重要的关键词:有序。如果这个条件缺少,二分查找就不能使用!所以基础排序算法的掌握也是极其重要的一个知识点,大家也应好好掌握。(额外话:这里也有一个萌妹子程序员的故事,如果大家感兴趣,我下期可以跟大家分享一下(^_^)
二分查找的工作原理
-
初始化范围:二分查找开始时,定义一个查找范围,该范围由数组的起始索引
low
和结束索引high
决定。 -
计算中间点:在每次迭代中,计算当前范围的中间索引
mid
,通常使用公式:
-
比较元素:
- 如果目标元素
x
等于arr[mid]
,则直接返回mid
作为目标元素的索引。 - 如果目标元素
x
小于arr[mid]
,则目标元素可能位于左半部分,因此将查找范围缩小为low
到mid-1
。 - 如果目标元素
x
大于arr[mid]
,则目标元素可能位于右半部分,因此将查找范围缩小为mid+1
到high
。
- 如果目标元素
-
重复过程:重复步骤2和3,直到找到目标元素或查找范围为空(即
low
大于high
),此时返回-1
,表示元素不在数组中。
二分查找的示例
可能光讲概念,大家可能就有些晕了,并说到:“这都是讲的写什么啊。”所以,先别急着晕,我们来看一个例子,看完之后你就会觉得:“这也不过如此。”
假设我们有一个升序排列的数组 ,如上,我们要查找元素 4 的索引。
- 初始范围:
low = 0
,high = 8
(数组的索引范围)。 - 计算中间点:
mid = 4
,数组中的元素是arr[4] = 7
。- 因为
4 < 7
,我们知道目标元素在左半部分,调整范围:low = 0
,high = 3
。
- 因为
- 再次计算中间点:
mid = 1
,数组中的元素是arr[1] = 3
。- 因为
4 > 3
,我们知道目标元素在右半部分,调整范围:low = 2
,high = 3
。
- 因为
- 再次计算中间点:
mid = 2
,数组中的元素是arr[2] = 4
。找到目标元素,返回索引3
。
二分查找的时间复杂度
二分查找的时间复杂度为 O(log n)
,因为每次查找操作都将查找范围减半。与线性查找的 O(n)
相比,二分查找在处理大规模数据时非常高效。
注意事项
- 前提条件:二分查找要求数组必须是有序!有序!有序!这里我又说了三遍。
- 元素重复:如果数组中存在多个相同的元素,二分查找可能不会返回第一个出现的元素的索引,而是找到的任意一个。
代码实现
static int binary_search(int[] arr, int start, int end, int key)
{
int mid;
while (start <= end)
{
mid = (start + end) / 2;
if (arr[mid] < key)
start = mid + 1;
else if (arr[mid] > key)
end = mid - 1;
else
return mid;
}
return -1;
}
结语
最后,二分查找常用于查找问题的基础算法,广泛应用于各种需要高效查找的场景中,也是面试的高频问题,希望有需要的小伙伴好好参考一下,如果有问题还望指正,大家共同进步!更希望这能帮助到你!(^_^)