二分法
二分法的前提是 在有序数组中,所以如果一个数组是无序的,我们要先把无序数组变为有序数组。
二分查找的思路分析:(假设该数组为自左向右从小到大)
1.首先确定该数组的中间的下标
mid = (left + right) / 2
2.然后让需要查找的数 findVal 和 arr[mid] 比较
有三种情况:
2.1 findVal > arr[mid],说明你要查找的数在mid的右边,因此需要递归的向右查找 2.2 findVal < arr[mid],说明你要查找的数在mid的左边,因此需要递归的想做查找 2.3 findVal = arr[mid],说明找到,就返回
// 什么时候我们需要结束递归呢?
有两种情况:
1.找到数就结束递归
2.递归完整个数组,仍然没有找到 findVal ,也需要结束递归,即 left > right 就需要退出。
代码实现(基本写法):
题目:请对一个有序数组进行二分查找{1, 8, 10, 89, 1000, 1234},输入一个数看看该数组是否存在该数,并且求出下标,否则就提示,没有这个数。
/** * @program: Julih * @description: * @author: wangxp * @create: 2019-11-18 21:40 */ // 注意: 使用二分查找的前提是,数组是有序的. public class BinarySearch { public static void main(String[] args) { int arr[] = {1, 8, 10, 89, 1000, 1234}; int resIndex = binarySearch(arr, 0, arr.length - 1, 1111); System.out.println("resIndex is " + resIndex); } /** * 二分查找算法 * @param arr 数组 * @param left 左边的索引 * @param right 右边的索引 * @param findVal 要查找的值 * @return 如果找到就返回下标,否咋返回-1 */ public static int binarySearch(int[] arr, int left, int right, int findVal){ if (left > right){ // 如果没有找到,就直接返回 -1 return -1; } int mid = (left + right) / 2; int midVal = arr[mid]; if (findVal > midVal){ // 向右递归 return binarySearch(arr, mid+1, right,findVal); } else if (findVal < midVal){ // 向左递归 return binarySearch(arr,left,mid -1, findVal); } else{ // 正好相等,找到了 return mid; } } }
二分查找(升级版):
题目:{1, 8, 10, 89, 1000, 1000,1000,1234},当一个有序数组中,有多个相同数值时,如何将所有的数值都查找到,比如这里的1000?
/** * @program: Julih * @description: * @author: wangxp * @create: 2019-11-18 21:40 */ // 注意: 使用二分查找的前提是,数组是有序的. public class BinarySearch2 { public static void main(String[] args) { int arr[] = {1, 8, 10, 89, 1000, 1000, 1000, 1234}; List<Integer> resIndexList = binarySearch(arr, 0, arr.length - 1, 1000); System.out.println("resIndexList is " + resIndexList.toString()); } /** * 二分查找算法 * @param arr 数组 * @param left 左边的索引 * @param right 右边的索引 * @param findVal 要查找的值 * @return 如果找到就返回下标,否咋返回-1 */ public static List<Integer> binarySearch(int[] arr, int left, int right, int findVal){ if (left > right){ // 如果没有找到,就直接返回 -1 return new ArrayList<Integer>(); } int mid = (left + right) / 2; // 中间的下标 int midVal = arr[mid]; // 中间的值 if (findVal > midVal){ // 向右递归 return binarySearch(arr, mid+1, right,findVal); } else if (findVal < midVal){ // 向左递归 return binarySearch(arr,left,mid -1, findVal); } else{ // 当已经找到的时候,先不退出, List<Integer> resIndexList = new ArrayList<Integer>(); // 向mid 索引值得左边扫描,将与findVal相等的值得下标,加入到ArrayList中. int temp = mid - 1; while (true){ if (temp < 0 || arr[temp] != findVal){ // 退出 break; } // 否则,将 temp 放入到 resIndexList中 resIndexList.add(temp); temp -= 1; // 左移 } resIndexList.add(mid); // 向mid 索引值得左边扫描,将与findVal相等的值得下标,加入到ArrayList中. temp = mid + 1; while (true){ if (temp > arr.length -1 || arr[temp] != findVal){ break; } // 否则,将 temp 放入到 resIndexList中 resIndexList.add(temp); temp += 1; // 右移 } return resIndexList; } } }