數據結構學習(十二):二分查找

一、思路

  1. 首先確定該數組的中間的下標;
  2. 然後讓需要查找的數findVal和arr[mid]比較;
    2.1 findVal>arr[mid],說明要查找的數在mid的右邊,因此需要遞歸地向右查找;
    2.2 findVal<arr[mid],說明要查找的數在mid的左邊,因此需要遞歸地向左查找;
    2.3 findVal==arr[mid],找到,返回;
  3. 什麼時候結束遞歸
    3.1 找到結束遞歸;
    3.2 遞歸完整個數組,仍然沒有找到findVal,left>right時結束。

二、代碼

//arr:數組
    //left:左邊的索引
    //right:右邊的索引
    //findVal:要找的值
    //如果找到就返回下標,沒有找到就返回-1
    public static int binarySearch(int[] arr, int left, int right, int findVal) {
        //當left > right時,說明遞歸整個數組,但是沒有找到
        if(left > right) {
            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.找到mid索引值,不要馬上返回
        2.向mid的左邊掃描,將所有滿足1000元素的下標,加入到ArrayList
        3.向mid的右邊掃描,將所有滿足1000元素的下標,加入到ArrayList
        4.將ArrayList返回
     */
    public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
        //當left > right時,說明遞歸整個數組,但是沒有找到
        if(left > right) {
            return new ArrayList<Integer>();
        }

        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if(findVal > midVal) { //向右遞歸
            return binarySearch2(arr, mid + 1, right, findVal);
        }else if(findVal < midVal) { //向左遞歸
            return binarySearch2(arr, left, mid - 1, findVal);
        }else {
            ArrayList<Integer> resIndexList = new ArrayList<>();

            //向mid的左邊掃描,將所有滿足1000元素的下標,加入到ArrayList
            int temp = mid - 1;
            while (true) {
                //退出
                if(temp < 0 || arr[temp] != findVal) {
                    break;
                }

                //將temp放入到resIndexList
                resIndexList.add(temp);
                //temp左移
                temp -= 1;
            }
            resIndexList.add(mid);

            //向mid的右邊掃描,將所有滿足1000元素的下標,加入到ArrayList
            temp = mid + 1;
            while (true) {
                //退出
                if(temp > arr.length - 1 || arr[temp] != findVal) {
                    break;
                }

                //將temp放入到resIndexList
                resIndexList.add(temp);
                //temp右移
                temp += 1;
            }

            return resIndexList;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章