力扣之二分查詢

水冗水孚發表於2022-07-09

題目描述

給定一個 n 個元素有序的(升序)整型陣列 nums 和一個目標值 target  ,寫一個函式搜尋 nums 中的 target,如果目標值存在返回下標,否則返回 -1

示例 1:

輸入: nums = [-1,0,3,5,9,12], target = 9
輸出: 4
解釋: 9 出現在 nums 中並且下標為 4

示例 2:

輸入: nums = [-1,0,3,5,9,12], target = 2
輸出: -1
解釋: 2 不存在 nums 中因此返回 -1
力扣原題目地址:https://leetcode.cn/problems/...

解法一,使用陣列原生方法indexOf

var search = function (nums, target) {
    return nums.indexOf(target)
};

陣列的原生方法,使用真方便。不過有時候需要多擴充一些處理問題的方式,以後遇到需求時,大有裨益

解法二,迴圈所有判斷是否等於目標值

var search = function (nums, target) {
    let whichIndex = -1
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] == target) {
            whichIndex = i
            return whichIndex
        }
    }
    return whichIndex
};

假設我們要找的值,就是正好在最後一個位置,那麼就得把整個迴圈全部走一遍,才能找到我們所要找的那個數值。所以時間複雜度就是O(n)。為了進一步提升效率,減少用時,所以二分法解題的方式就應運而生

解法三,二分法解題

所謂二分法可以簡單理解為:

  • 指定開始位置、結束位置、然後不斷縮小其範圍最終找到我們想要找到的值;
  • 由於二分法的一半一半的縮小範圍,所以其時間複雜度是O(\log n)

另外注意:

  • 二分法適用於有序的陣列,即從小到大或者從大到小的陣列
  • 二分法搭配while迴圈可讀性會更加直觀明瞭

在工作中for迴圈使用次數比較多,while迴圈並不是特別多,所以為了更好的理解二分法的,我們來簡單複習一下while的迴圈知識

while迴圈複習

// 當符合condition條件的時候,會繼續不斷迴圈執行花括號裡面的程式碼
// 所以當達到某種情況下的時候,需要讓condition條件變為false,這樣的話,才會結束迴圈
// 要不然就會死迴圈哦
while (condition) {
     // .....       
}

// eg:使用while迴圈列印0~10
let num = 0
while (num <= 10) { // 翻譯:當num的值小於等於10的時候,就不斷迴圈
    console.log(num);
    num++
}

while和for迴圈的區別

  • 固定陣列、固定長度、固定執行次數一般使用for迴圈
  • 做邊界區分、不知道要迴圈多少次一般使用while迴圈
  • while比for功能更加強大

二分法程式碼

var search = function (arr, num) {
    let firstIndex = 0
    let lastIndex = arr.length - 1
    // 注意firstIndex是要小於等於lastIndex值的,因為區間不斷縮小最終重合
    while (firstIndex <= lastIndex) { 
        // console.log('firstIndex', firstIndex, 'lastIndex', lastIndex); // 看列印結果,有助於更好理解
        let middleIndex = Math.floor((firstIndex + lastIndex) / 2) // 陣列長度為偶數時要向下取整,所以乾脆都向下取整唄
        if (arr[middleIndex] == num) { // 若恰好中間索引數正好是我們所要找的那個數,返回索引即可
            return middleIndex
        } else if (arr[middleIndex] > num) { // 若中間數比要找的數大,說明要找到數在左邊,那麼開始區間不用動,結束區間更改為中間數左邊一個位置即可
            lastIndex = middleIndex - 1
        } else if (arr[middleIndex] < num) { // 同理...
            firstIndex = middleIndex + 1
        }
    }
    return -1 // 找不到的話,返回-1
};

這裡大家可以把while (firstIndex <= lastIndex) {......}改為while (true) {......}看看列印結果就會更好的理解了。雖然會死迴圈

相關文章