2020.2.9
13:14
二分法
定义:假设数据是按升序排序的,对于给定值key,从序列的中间位置k开始比较,
如果当前位置arr[k]值等于key,则查找成功;
若key小于当前位置值arr[k],则在数列的前半段中查找,arr[low,mid-1];
若key大于当前位置值arr[k],则在数列的后半段中继续查找arr[mid+1,high],
直到找到为止,时间复杂度:O(log(n)) [3] 。
(前提:数组在查找前一定是已经排好序的)
传统循环写法:
//传统的循环写法
public class binarySearch {
public static int search(int[] arr, int key) {
int begin = 0; //高位
int end = arr.length - 1; //低位
while (begin <= end) {
int middle = (begin + end) / 2; //中间位
if (key < arr[middle]) { //查找的元素在左边
end = middle - 1; //重新赋值高位
} else if (key > arr[middle]) { //查找的元素在右边
begin = middle + 1; //重新赋值低位
} else {
return middle;
}
}
return -1; //没有找到返回-1
}
递归写法:
思路:全范围内二分法查找
等价于三个子问题:
①左边查找(递归)
②中间比
③右边查找(递归)
(注意:左边查找和右边查找只能二选一,给人的感觉更像是一种多分支的递归,但是又是
一种单链的线性结构,线性结构有点类似于求阶乘的样子)
递归代码:
//递归写法
static int Search2(int []arr,int low,int high,int key) {
if(low>high) {
return -1;
}
int mid=low+((high+low)>>1); //利用移位来防止栈溢出,比较高效
int midval=arr[mid];
if(midval<key) {
return Search2(arr,mid+1,high,key);
}
else if(midval>key) {
return Search2(arr,low,high-1,key);
}
else {
return mid;
}
}
(一般情况下,递归的代码写出来十分的简洁明了,但是,我怎么感觉递归的代码写出来这么复杂呢,比传统的循环写出来的代码还要长)
附上两种方法的比较完整代码:
package LanQiaoKnowledgePractise;
//二分法查找元素
//传统的循环写法
public class binarySearch {
public static int search(int[] arr, int key) {
int begin = 0; //高位
int end = arr.length - 1; //低位
while (begin <= end) {
int middle = (begin + end) / 2; //中间位
if (key < arr[middle]) { //查找的元素在左边
end = middle - 1; //重新赋值高位
} else if (key > arr[middle]) { //查找的元素在右边
begin = middle + 1; //重新赋值低位
} else {
return middle;
}
}
return -1; //没有找到返回-1
}
//递归写法
static int Search2(int []arr,int low,int high,int key) {
if(low>high) {
return -1;
}
int mid=low+((high+low)>>1); //利用移位来防止栈溢出,比较高效
int midval=arr[mid];
if(midval<key) {
return Search2(arr,mid+1,high,key);
}
else if(midval>key) {
return Search2(arr,low,high-1,key);
}
else {
return mid;
}
}
public static void main(String[] args) {
int []arr={1,2,3,4,5,6};
System.out.println( search(arr ,5) );
System.out.println("*****************************");
System.out.println( Search2(arr,1,5,3) );
}
}
搞定收工!