面试题之二分法查找详解
Posted Fu_Lin_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题之二分法查找详解相关的知识,希望对你有一定的参考价值。
前言
回顾以往面试中,算法提到最多的就是二分法了,感觉简单,但是突然提到又难以入味,所以本文将整理总结出最简单的理论和程序实践,结合实际面试题来解答!
二分法概念
二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。
二分法 查找的思路 如下:
1.首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
2、如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤(1)的操作。
3. 如果某一步数组为空,则表示找不到目标元素。
二分法查找的时间复杂度O(logn)。
举例加深概念
文字说明一下二分法究竟是怎样的: 给定的数组是有序的,给定一个key值,每次查找最中间的值,如果相等,就返回对应的下标;如果key 大于 最中间的值,则在数组的 右半边 继续查找;如果 小于,则在数组的 左半边 查找。那么最终存在两种结果:一种是找到了并返回对应的下标,第二种就是没有找到,返回-1。
举例说明:
存在一个数组arr[10],假设arr[10]={3,6,7,9,15,20,26,33,56,63},定义两个边界的下标low和high,以及中间下标mid, 记住,数组前提一定是排序好了的,排序方法可见我后面博文会涉及到
int low=0;
int high=10-1;
int mid=(low+high)/2;
在对每一步进行比较的时候,low<=high,如果要找key为56的值对应的下标,那么第一次我们先找到中间下标mid=4。因为arr[4]=15,比当前的key值要小,则按照要求在数组的右半部分查找,让low=mid+1,high值不变。接下来,我们继续找到右半部分的中间下标 mid = (5+9)/2=7,arr[7]=33,比当前的key值还小,那么继续向右半边查找,且 low=mid+1,high值继续不变。接下来,找到中间下标mid=(8+9)/2=8。这个时候arr[8]key56,OK,找到目标值,停止查找,返回下标mid。
通过上面例子可以看出,在进行指定key查找的次数总共3次,通过根据中间值和目标key进行比较来判定目标key的位置。接下来给出相关处理代码:
非递归算法:
C实现写法:
int binarySearch(int arr[], int arrSize, int key)
{
int low=0; //数组最小索引值
int high=arrSize -1; //数组最大索引值
while(low<=high){
int mid= floor((low+high)/2);
if(key==arr[mid]){
return mid;
}else if(key>arr[mid]){
low=mid+1;
}else{
high=mid-1;
}
}
return -1; //low>high的情况,这种情况下key的值大于arr中最大的元素值或者key的值小于arr中最小的元素值
}
Main调用如下
int arr[10]={3,6,7,9,15,20,26,33,56,63};
for(auto arrayValue:arr){
qInfo()<<"Array = "<<arrayValue;
}
QTime time;
time.start();
int key = binarySearch(arr, 10, 56);
qInfo()<<"find key = "<<key;
qInfo()<<"花费时间 :"<<time.elapsed()/1000.0<<"秒";
结果测试:
Array = 3
Array = 6
Array = 7
Array = 9
Array = 15
Array = 20
Array = 26
Array = 33
Array = 56
Array = 63
find key = 8
花费时间 : 0 秒
js 实现写法:
function binarySearch(arr,key){
var low=0; //数组最小索引值
var high=arr.length-1; //数组最大索引值
while(low<=high){
var mid=Math.floor((low+high)/2);
if(key==arr[mid]){
return mid;
}else if(key>arr[mid]){
low=mid+1;
}else{
high=mid-1;
}
}
return -1; //low>high的情况,这种情况下key的值大于arr中最大的元素值或者key的值小于arr中最小的元素值
}
递归算法:
C类语言实现
int binarySearch(int arr[], int low, int high,int key){
if(low>high)
{
return -1;
}
int mid= floor((low+high)/2);
if(key==arr[mid]){
return mid;
}else if(key<arr[mid]){
high=mid-1;
return binarySearch(arr,low,high,key);
}else{
low=mid+1;
return binarySearch(arr,low,high,key);
}
}
Main调用如下:
int arr[10]={3,6,7,9,15,20,26,33,56,63};
for(auto arrayValue:arr){
qInfo()<<"Array = "<<arrayValue;
}
QTime time;
time.start();
int key = binarySearch(arr, 0, 9, 56);
qInfo()<<"find key = "<<key;
qInfo()<<"花费时间 :"<<time.elapsed()/1000.0<<"秒";
结果测试:
Array = 3
Array = 6
Array = 7
Array = 9
Array = 15
Array = 20
Array = 26
Array = 33
Array = 56
Array = 63
find key = 8
花费时间 : 0 秒
可见递归和非递归查找的速度都是一样的快,要真正看速度还得需要上百上千的数据才能看出性能如何!
js 语言实现
function binarySearch(arr,low,high,key){
if(low>high){return -1;}
var mid=Math.floor((low+high)/2);
if(key==arr[mid]){
return mid;
}else if(key<arr[mid]){
high=mid-1;
return binarySearch(arr,low,high,key);
}else{
low=mid+1;
return binarySearch(arr,low,high,key);
}
}
以上是关于面试题之二分法查找详解的主要内容,如果未能解决你的问题,请参考以下文章