學算法,先從二分查找開始吧

總綱

思路很簡單,細節是魔鬼。分爲三個常用場景:尋找一個數,尋找左側邊界,尋找右側邊界。最後給出力扣上的題目例子。
還可以在GitHub上觀看哦。AlgorithmNotes

基礎框架

int binarySearch(int[] nums, int target) {
    int left = 0, right = ...;
    
    while(...) {
        int mid = (right + left) / 2;
        if (nums[mid] == target) {
            ...
        } else if (nums[mid] < target) {
            left = ...
        } else if (nums[mid] > target) {
            right = ...
        }
    }
    return ...;
}
  • 把所有情況都寫清楚,展示所有細節。
  • mid = left + (right - left) / 2,防止溢出。
  • 三個框架可以合成一個,但適用面很小,不如單獨的左區間或右區間使用廣。

尋找一個數

int binarySearch(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1; 

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target)
            return mid;
        else if (nums[mid] < target)
            left = mid + 1; 
        else if (nums[mid] > target)
            right = mid - 1; 
    }
    return -1;
}

最基礎的二分查找,每次查找都是左閉右閉區間。

  • 循環條件是 <=;
  • 更新是 left=mid+1,right=mid-1。

必要條件是數組內無重複整數。

尋找左側邊界

int left_bound(int[] nums, int target) {
    if (nums.length == 0) return -1;
    int left = 0;
    int right = nums.length;
    
    while (left < right) { 
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
            right = mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid;
        }
    }
    
    return left;//此處返回left,right都可,因爲相等
}

每次查找都是左閉右開區間。

  • 循環條件是 left < right;
  • 更新是 left = mid + 1, right = mid,可以理解爲下一次搜索區間是 [left,mid), [mid+1,right)
  • 每次找到target時,因爲存在重複數字且要找的是左邊界,所以不斷向左收縮, right = mid。

尋找右側邊界

int right_bound(int[] nums, int target) {
    if (nums.length == 0) return -1;
    int left = 0, right = nums.length;
    
    while (left < right) {
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
            left = mid + 1; 
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid;
        }
    }
    
    return left - 1; 
}
  • 循環條件是 left < right;
  • 更新是 left = mid + 1, right = mid,可以理解爲下一次搜索區間是 [left,mid), [mid+1,right);
  • 每次找到target時,因爲存在重複數字且要找的是右邊界,所以不斷向右收縮, left = mid + 1;
  • 返回 left - 1,因爲更新時 left = mid + 1,所以循環結束時 nums[left-1] 纔是target。

題目

題號 題目 鏈接
704 二分查找(打板題) 105265723
33 搜索旋轉排序數組 105265887
35 搜索插入位置(打板題) 105265922
153 尋找旋轉排序數組中的最小值 105265935
154 尋找旋轉排序數組中的最小值II 105265998
162 尋找峯值 105266055
275 H指數II 105266073
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章