Java算法篇之二分查找算法

1 Java算法篇之二分查找算法

1.1 什麼是二分查找算法?

  • 算法定義

二分查找算法又叫折半查找算法, 是一種基於比較目標值和數組中間元素的教科書式算

  • 使用條件

待查找的數組必須是有順序的

  • 複雜度

空間複雜度:O(1)

  • 時間複雜度最好情況:O(1)
  • 時間複雜度最壞情況:O(LogN) 一般默認指這種。
    注意:
    可能也聽過下面這種說法:
    在這裏插入圖片描述
    它們兩個其實是等價的,log2n 的意思是以2爲底數,然後n.
  • 算法規則
  • 如果目標值等於中間元素,則找到目標值。
  • 如果目標值較小,繼續在左側搜索。
  • 如果目標值較大,則繼續在右側搜索。
    在這裏插入圖片描述

1.2 二分查找算法分析

LeetCode最佳算法解析,請移步二分查找細節詳解,順便賦詩一首

  • 初始化指針 left = 0, right = n - 1。
  • 當 left <= right:
  • 比較中間元素 nums[pivot] 和目標值 target 。
    • 如果 target = nums[pivot],返回 pivot。
    • 如果 target < nums[pivot],則在左側繼續搜索 right = pivot - 1。
    • 如果 target > nums[pivot],則在右側繼續搜索 left = pivot + 1。
      在這裏插入圖片描述

1.3 Solution

1.3.1 LeetCode 官方解法

LeetCode 官方二分法解法

class Solution {
  public int search(int[] nums, int target) {
    int pivot, left = 0, right = nums.length - 1;
    while (left <= right) {
      pivot = left + (right - left) / 2;
      if (nums[pivot] == target) return pivot;
      if (target < nums[pivot]) right = pivot - 1;
      else left = pivot + 1;
    }
    return -1;
  }
}

作者:LeetCode
鏈接:https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-by-leetcode/
來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

1.3.2 最佳二分法查找Solution

給大家講個笑話樂呵一下:

  • 有一天阿東到圖書館借了 N本書,出圖書館的時候,警報響了,於是保安把阿東攔下,要檢查一下哪本書沒有登記出借。阿東正準備把每一本書在報警器下過一下,以找出引發警報的書,但是保安露出不屑的眼神:你連二分查找都不會嗎?於是保安把書分成兩堆,讓第一堆過一下報警器,報警器響;於是再把這堆書分成兩堆……
  • 最終,檢測了 logN 次之後,保安成功的找到了那本引起警報的書,露出了得意和嘲諷的笑容。於是阿東揹着剩下的書走了。
  • 從此,圖書館丟了 N - 1 本書。

事故現場還原:

數組下標:0 1 2 3 4 
存儲內容:1 2 2 2 3

比如說給你有序數組 nums = [1,2,2,2,3],target 爲 2,上面算法返回的索引是 2,沒錯。但是如果我想得到 target 的左側邊界,即索引 1,或者我想得到 target 的右側邊界,即索引 3,這樣的話此算法是無法處理的。

解決上述需求,完整算法如下:

保安用的基礎二分法算法如下:

//和官方的Leetcode 算法一致
//基礎二分查找算法
int binary_search(int[] nums, int target) {
    int left = 0, right = nums.length - 1; 
    while(left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            // 搜索區間變爲 [mid+1, right]
            left = mid + 1;
        } else if (nums[mid] > target) {
            // 搜索區間變爲 [left, mid-1]
            right = mid - 1; 
        } else if(nums[mid] == target) {
            // 直接返回
            return mid;
        }
    }
    // 直接返回
    return -1;
}

左側邊界二分法算法如下:

//左側邊界查找算法
int left_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 別返回,收縮左側邊界
            right = mid - 1;
        }
    }
    // 最後要檢查 left 越界的情況
    if (left >= nums.length || nums[left] != target){
        return -1;
    }
    return left;
}

右側邊界二分法算法如下:

//右側邊界查詢算法
int right_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 別返回,收縮右側邊界
            left = mid + 1;
        }
    }
    // 最後要檢查 right 越界的情況
    if (right < 0 || nums[right] != target){
        return -1;
    }
    return right;
}

作者:labuladong
鏈接:https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-xiang-jie-by-labuladong/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

本篇完~

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