/**
* 二分法 dichotomy 也称 binarySearch
* 思想:一分为二
* 设[a,b]为闭区间,逐次二分就是找到中点n,造出如下区间[a,n] [n,b]
* 再对确定的某一区间[a,n]或者[n,b]进行二分
* 以[a,n] 为例,m为中点,分为[a,m] [m,n]
* 以此下去,直到找到为止
* 二分常用作数组中某一元素查找,可提高效率,仅对有序数组有效
* <p>
* 源码:Arrays.binarySearch(int[] a,int key);
*/
public class TestDichotomyFind {
public static void main(String[] args) {
int[] array = {1,3,5,7,9};
int i = halfSearch(array, 9);
System.out.println(i);
}
/**
* @param array 有序的数组
* @param key 查找的值
* @return 位置下标
*/
public static int halfSearch(int[] array, int key) {
//根据区间边界确定中点,以分割
//定义三个变量,最小边界、中点、最大边界
int min, mid, max;
min = 0;
max = array.length - 1;
mid = (min + max) / 2;
//当前中点值不是查找值时,一直循环
while (array[mid] != key) {
//分为两种情况:key在右边的区间、或者 左边的区间
if (key > array[mid]) {
min = mid + 1;
} else if (key < array[mid]) {
max = mid - 1;
}
//如果不存在 查找值,返回-1
/**
* 此步骤如果较难理解,可以画图
* 如:
* 数组{1,2,3,4,5}
* 找66 则最后 min == max = 数组最后一个位置,再往后,则产生min>max 超出数组边界
* 找-1 则最后 min == max = 数组第一个位置,再往前,则产生min>max 超出数组边界
*/
if (min > max) {
return -1;
}
//下一次区间的中点值
mid = (min + max) / 2;
}
return mid;
}
}
进行优化
import java.util.Arrays;
/**
* @author:秦淏
* @version:2021年2月21日
* @TODO:
*/
public class Main06B {
/*
* 进行部分优化
*/
public static void main(String[] args) {
int[] a = { 1, 8, 16, 3, 7, 9, 10, 88, 666, 4, 6 };
Arrays.sort(a);
System.out.println(halfSeach(a,0,a.length-1,666));
}
/*
* min:左边界
* max:右边界
*/
public static int halfSeach(int[] array, int min, int max, int key) {
while (min <= max) {
int mid = (min + max) >> 1;
if (array[mid] == key) {
return mid;
} else if (array[mid] > key) {
max = mid - 1;
} else {
min = mid + 1;
}
}
return -1;
}
}
递归解法
import java.util.Arrays;
/**
* @author:秦淏
* @version:2021年2月21日
* @TODO:
*/
public class Main06C {
/*
* 递归
*/
public static void main(String[] args) {
int[] a = { 1, 8, 16, 3, 7, 9, 10, 88, 666, 4, 6 };
Arrays.sort(a);
System.out.println(halfSeach(a, 0, a.length - 1, 666));
}
public static int halfSeach(int[] array, int min, int max, int key) {
while (min <= max) {// 递归终止条件
int mid = (min + max) >> 1;
if (array[mid] == key) {// 简单情境
return mid;
} else if (array[mid] > key) {
// 递归调用,缩小问题规模
return halfSeach(array, min, mid - 1, key);
} else {
// 递归调用,缩小问题规模
return halfSeach(array, mid + 1, max, key);
}
}
return -1;
}
}