背景
今天無意中聽見公司前輩說他給來公司面試的出了道二分查找的手寫算法題,嗯嗯嗯,那就對這個二分查找進行簡單思考。
題目
具體啥題目就沒繼續深入問了,那我自己給自己出了小題目:“給定一個元素有序分佈的數組,要求查找某個的元素,如果找到返回元素下標,如果沒有則返回-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;
}
}
當然,題目也可以再變變,但是主要思想還是不變的。就是二分法和適合二分法的利用場景