[老實李] 算法初探:二分查找法 Binary Search

二分查找法主要用來解決查找的問題

1、二分查找法Binary Search

(注)對于有序數列才能使用二分查找法。

Image.png

二分查找的一個基本思想:找到數組的中間位置的元素v,將數組分成>v和<v兩部分,然后將v和要查找的數據進行一個比較,如果大于v那么就在>v的部分再次進行二分查找,否則就在<v的部分進行二分查找,直到找到對應的元素。
雖然二分查找法的基本思想是非常簡單的,但是第一個無BUG的二分查找法的實現卻經歷了幾十年才出現。下面我們來看這個二分查找法的基本代碼實現。

public static int binartSearch(int arr[], int target) {
           // 在arr[l...r]之中查找target
           int l = 0;
           int r = arr.length - 1;

           while (l <= r) {
                int mid = (l+r) / 2;
                if (arr[mid] == target)
                     return mid;
                // 在arr[mid+1...r]之中繼續查找target
                if (arr[mid] < target)
                     l = mid + 1;
                else
                // 在arr[l...mid-1]之中繼續查找target
                     r = mid - 1;

           }
           return -1;
     }

很簡單就實現了出來,但是現在是有BUG的。請看上面加粗的那一行代碼,l和r都是一個int型,相加有可能會出現超過int取值范圍,所以第一個BUG的修改為:

int mid = l + (r - l) / 2;

就是用最小的值加上左右兩邊的一個范圍,將加法換成了減法。這樣我們就寫出了一個無BUG的二分查找法。

2、floor和ceil函數

floor和ceil是二分查找法的函數,我們在上面的基礎二分查找法中實現的二分查找雖然也可以找到相應的target元素,但是當這個元素在數組中重復出現好幾次的時候,如果我們要找到這個元素第一出現的位置就可以使用floor函數,最后一次出現的位置就可以使用ceil函數。


Image.png

另外,當我們查找的元素在數組中不存在的話,上面的基礎實現就會直接返回一個-1,但是使用floor和ceil函數返回的結果就不一樣了。比如我們要查找42這個元素,floor函數會返回最后一個41,ceil則會返回第一個43。

Image.png

因為這兩個函數比較復雜,感興趣的可以自行百度。

3、使用遞歸實現二分查找

// 使用遞歸的方式實現二分查找法
     public static int binarySearch2(int arr[], int target){
           return __binarySearch2(arr,0,arr.length-1,target);
     }
     public static int __binarySearch2(int arr[],int l,int r, int target) {

           if (l > r) {
                return -1;
           }
           int mid = (l+r)/2;
           if (arr[mid] == target)
                return mid;
           else if (arr[mid]> target)
                return __binarySearch2(arr, 0,mid-1,target);
           else

                return __binarySearch2(arr, mid+1, r, target);
     }

使用遞歸的效率會稍微慢一些,但是邏輯上更簡單清晰。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一、基本數據類型 注釋 單行注釋:// 區域注釋:/* */ 文檔注釋:/** */ 數值 對于byte類型而言...
    龍貓小爺閱讀 4,288評論 0 16
  • 第5章 引用類型(返回首頁) 本章內容 使用對象 創建并操作數組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,265評論 0 4
  • 第1章 認識JS JavaScript能做什么?1.增強頁面動態效果(如:下拉菜單、圖片輪播、信息滾動等)2.實現...
    mo默22閱讀 1,319評論 0 5
  • 來源:NumPy Tutorial - TutorialsPoint 譯者:飛龍 協議:CC BY-NC-SA 4...
    布客飛龍閱讀 32,952評論 6 98
  • 童話中的舞鞋 完美卻易幻滅 現實總是殘缺 你不在我身邊 城堡依然覆雪 圍墻都已傾斜 殘破不堪荒野 誰丟棄了一切 相...
    萬象live閱讀 210評論 0 0