讓我們一起啃演算法----搜尋插入位置

三斤和他的喵發表於2020-04-26

搜尋插入位置( Search-Insert-Position )

題幹:

給定一個排序陣列和一個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。
你可以假設陣列中無重複元素。
示例 1:
  輸入: [1,3,5,6], 5
  輸入: 輸出: 2
示例 3:
  輸入: 輸入: [1,3,5,6], 7
  輸入: 輸出: 4
示例 4:
  輸入: 輸入: [1,3,5,6], 0
  輸入: 輸出: 0
來源:力扣

這題主要應用 二分查詢 的思路來解題,題目是比較簡單的,但是 二分查詢 這個思路還是蠻重要的。

解題思路

一般使用 二分查詢 都需要先對原陣列進行排序,題中給到的陣列是已經排序的,因此這一步可以省去。

二分查詢 思路比較簡單,首先初始化三個指標: left 指向 nums 最左邊的元素,right 指向 nums 右邊的元素,根據 left 和 right 計算 mid 指標。我們先拿目標值 target 與 nums[mid] 進行比較。

如果 target > nums[mid],說明要查詢的值有可能在 nums[mid+1, right] 之間,這時候將 left 賦值為 mid + 1,right 不變,重新計算一下 mid,重新比較

如果 target < nums[mid],說明要查詢的值有可能在 nums[left, mid-1] 之間,這時候將 right 賦值為 mid - 1,left 不變,重新計算一下mid,重新比較

如果 target == nums[mid],那麼恭喜找到啦,根據題意,找到的索引值就是 target 插入的目標位置,即返回 mid 即可。

如果 二分查詢 結束仍是沒有找到 target 的值,最後返回 left 就可以了,至於為什麼 left 的值是 target 插入的位置,可以看流程圖的分析。

mid 的計算方式: mid = left + ( rigth - left ) / 2,至於為什麼不用 ( left + right ) / 2 來計算 mid 是因為 right + left 有可能溢位。
注: ( right - left) / 2 取整,因為陣列的索引值是整數。

流程圖如下:

程式碼實現

// 函式的實現並不是最簡潔的,但是整個二分法思路是很清晰的。
func searchInsert(nums []int, target int) int {
    if len(nums) <= 0 {
        return 0
    }

    var left, right = 0, len(nums) - 1
    for left <= right {

        // 根據 left 和 right 計算 mid 的值
        mid := left + (right - left) / 2  // ( left + right ) / 2


        // 目標值大於中間值,left = mid + 1
        if nums[mid] < target {
            left = mid + 1

        // 目標值小於中間值 right = mid - 1
        } else if nums[mid] > target {
            right = mid - 1
        } else {
            // 目標值等於中間值返回 mid,即為目標值需要插入的位置
            return mid
        }
    }

    // 找不到目標值,這時候返回left就是目標值需要插入的位置
    return left

}

總結

每天進步一點點,加油!
演算法教程專案,每天更新一題,點個 star 支援一下呀
https://github.com/wx-satellite/learning-a…

本作品採用《CC 協議》,轉載必須註明作者和本文連結

三斤

相關文章