從酒桌遊戲看二分查找算法

圖怪獸_a333ddb7d5a4c52a6b2d361d2a272c35_92006.png
觀感度:🌟🌟🌟🌟🌟前端

口味:孜然牛肉python

烹飪時間:5mingit

本文已收錄在 Github github.com/Geekhyt,感謝Star。

酒桌上曾經玩過這樣一個小遊戲,遊戲規則是:主持人每次隨機從 1-1000 中選擇一個數字,好比是 171。只有主持人本身知道並事先寫在紙條上留存,而後分別讓你們來猜,可以用最少次數猜到的人獲勝並擁有指定一我的罰酒的權利。github

  • 童歐巴:500
  • 主持人:大了
  • 童歐巴:250
  • 主持人:大了
  • 童歐巴:125
  • 主持人:小了
  • 童歐巴:187
  • 主持人:大了
  • 童歐巴:156
  • 主持人:小了
  • 童歐巴:171

主持人再次挑選數字,讓扒蒜小妹去猜...算法

最後,童歐巴用的次數最少,童歐巴獲勝!指定扒蒜小妹罰酒。數組

這個遊戲就是看誰能使用最少的次數猜到主持人選的數字,誰就獲勝。這種在有序數據集合中的查找用二分查找再合適不過了。spa

二分查找 Binary Search

二分查找,顧名思義。(看上文歐巴熟練的灌酒操做也能夠知道)每次的查找都是和區間的中間元素對比,將待查找的區間縮小爲一半,直到找到目標元素,或者區間被縮小爲 0 (沒找到)。二分查找的時間複雜度是 O(logn)。對比常量級時間複雜度,當常量很大時 O(999999),就會比 O(1) 的算法要高效。3d

二分算法雖然高效,但也存在必定的侷限性。想要使二分查找發揮威力,須要知足幾個前置條件才行。code

  • 有序(單調遞增/遞減)
  • 數組(可以經過索引訪問)
  • 數據量不能太大(數組內存空間連續,對內存要求嚴格)也不能過小(遍歷便可)

LeetCode 真題

33. 搜索旋轉排序數組blog

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。

( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。

搜索一個給定的目標值,若是數組中存在這個目標值,則返回它的索引,不然返回 -1 。

你能夠假設數組中不存在重複的元素。

你的算法時間複雜度必須是 O(log n) 級別。

示例 1:

輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4

示例 2:

輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1

關鍵點

進行旋轉後的數組必定有一部分是有序的。並且,題目要求時間複雜度爲 O(logn),暗示咱們使用二分搜索。

如上圖中的兩種狀況,觀察旋轉後的數組:

  • nums[mid] >= nums[start] 時,mid 在左邊且左邊有序 5 >= 2
  • nums[mid] < nums[start] 時,mid 在右邊且右邊有序 2 < 6

接着咱們來判斷 target 在哪個部分,捨棄另外一部分便可。如上圖的第二種狀況,咱們假設 target黑色的 3mid 在右邊也就是 [mid, end]target > nums[mid] && target <= nums[end],因此捨棄左邊,start = mid + 1

const search = function(nums, target) {
    let start = 0;
    let end = nums.length - 1;
    
    while (start <= end) {
        const mid = start + ((end - start) >> 1);
        if (nums[mid] === target) {
            return mid;
        }
        // 左側有序
        if (nums[mid] >= nums[start]) {
            // target 在 [start, mid] 之間
            if (target >= nums[start] && target < nums[mid]) {
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        } else { // 右側有序
            // target 在 [mid, end] 之間
            if (target > nums[mid] && target <= nums[end]) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
    }
    return -1;
}

複雜度分析

  • 時間複雜度:O(logn)
  • 空間複雜度:O(1) 只須要常量級別的空間存放變量

❤️愛心三連擊

1.看到這裏了就點個贊支持下吧,你的是我創做的動力。

2.關注公衆號前端食堂,你的前端食堂,記得按時吃飯

3.本文已收錄在前端食堂Github github.com/Geekhyt,求個小星星,感謝Star。

qrcode.jpg

相關文章
相關標籤/搜索