二分法的前提是 在有序數組中,因此若是一個數組是無序的,咱們要先把無序數組變爲有序數組。算法
二分查找的思路分析:(假設該數組爲自左向右從小到大)數組
1.首先肯定該數組的中間的下標spa
mid = (left + right) / 2 code
2.而後讓須要查找的數 findVal 和 arr[mid] 比較blog
有三種狀況:遞歸
2.1 findVal > arr[mid],說明你要查找的數在mid的右邊,所以須要遞歸的向右查找 2.2 findVal < arr[mid],說明你要查找的數在mid的左邊,所以須要遞歸的想作查找 2.3 findVal = arr[mid],說明找到,就返回
// 何時咱們須要結束遞歸呢?索引
有兩種狀況:ip
1.找到數就結束遞歸io
2.遞歸完整個數組,仍然沒有找到 findVal ,也須要結束遞歸,即 left > right 就須要退出。class
代碼實現(基本寫法):
題目:請對一個有序數組進行二分查找{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; } } }