背景
今天无意中听见公司前辈说他给来公司面试的出了道二分查找的手写算法题,嗯嗯嗯,那就对这个二分查找进行简单思考。
题目
具体啥题目就没继续深入问了,那我自己给自己出了小题目:“给定一个元素有序分布的数组,要求查找某个的元素,如果找到返回元素下标,如果没有则返回-1,要求使用二分查找”;
idea
1.我首先居然不是想怎么查找,我想到的是,要是有重复元素,那怎么查找?找到那个才算是对的?这个我们待会改进再说,先谈简单又经典的二分查找,
2.主要思路就是,先选则一个数组中的中间元素arr[mid]和目标比较,
2.1 要是相等则是找见了,返回下标;
2.2 要是目标大于中间元素值,那么就从中间元素之后的数组中找,
2.3 要是目标小于中间元素值,那么就从中间元素之前的数组中找
3. 找不到就返回-1;
代码实现
#include <iostream>
using namespace std;
int binary(int arr[],int low, int high,const int &target){
if(arr == NULL){
cout<<"hi, big bro,please input correct params"<<endl;
}
if(low <= high){
int mid = (low + high) / 2;
if(arr[mid] == target){
return mid;
}else if(arr[mid] < target){
binary(arr, mid+1, high, target);
} else if(arr[mid] > target){
binary(arr, low, mid-1, target);
}
}
return -1;
}
int main() {
int target = 56;
int arr[] = {7,10,23,26,32,38,39,46,47,51,54,58,60,61,62,68,72,74,76,78,80,86,94,97,98};
int length = sizeof(arr)/sizeof(arr[0]);
int targetIndex= binary(arr,0,length-1,target);
if(targetIndex != -1){
cout<<"we found the target ,it`s index = "<<targetIndex<<endl;
} else {
cout<<"sorry, big bro,we couldn`t find the target "<<endl;
}
}
变形---含重复元素的二分查找
idea
如果有重复元素,如果我们当前查找的目标正好有多个,我们通过每次只能找到其中的一个,这里有三个可能性:
- 我们找到的正好是重复元素的第一个元素
- 我们找到的是重复元素中的中间某一个元素
- 我们找到的是重复元素的最后一个元素
哈哈,重复就重复吧,我们首先要知道我们为什么选择二分查找?如果是无序数组,我们用二分查找,可能需要遍历所有的元素才能找到目标,所以在选择二分查找,我们就相当知道了被查找数组的特性,有序的,那么重复的元素就还在一起,找到一个和找到所有就差别不大了。
那我就先把题目改一下:“给定一个元素有序分布的数组,要求查找某个的元素,如果找到返回元素下标,重复元素请返回第一次出现的元素下标,如果没有则返回-1,要求使用二分查找”
题目有小改动,思路也要小小改一下:
那我们就比较一下找到目标元素和执之前一个元素比较,如果相等就继续向前比较,直到某一次比较结果不相等,那就返回他的下标,他就是第一次出现!
思路有了小改动,代码也是要改动的:
代码实现
#include <iostream>
using namespace std;
int binary(int arr[],int low, int high,const int &target){
if(arr == NULL){
cout<<"hi, big bro,please input correct params"<<endl;
}
if(low <= high){
int mid = (low + high) / 2;
if(arr[mid] == target){
while(arr[mid - 1]== target){
mid--;
}
return mid;
}else if(arr[mid] < target){
binary(arr, mid+1, high, target);
} else if(arr[mid] > target){
binary(arr, low, mid-1, target);
}
}
return -1;
}
int main() {
int target = 61;
int arr[] = {7,10,23,26,32,38,38,39,46,47,51,54,58,60,61,61,61,61,61,61,62,62,68,72,74,76,78,80,86,94,97,98};
int length = sizeof(arr)/sizeof(arr[0]);
int targetIndex= binary(arr,0,length-1,target);
if(targetIndex != -1){
cout<<"we found the target ,it`s index = "<<targetIndex<<endl;
} else {
cout<<"sorry, big bro,we couldn`t find the target "<<endl;
}
}
当然,题目也可以再变变,但是主要思想还是不变的。就是二分法和适合二分法的利用场景