[LeetCode解題攻略] 35. Search Insert Position

更新於 發佈於 閱讀時間約 5 分鐘

問題描述

給定一個升序排序的整數數組 nums 和一個目標值 target,請找出目標值應插入的位置,保證插入後數組仍然是有序的。

必須設計一個演算法,其時間複雜度為 O(log n)


範例 1

輸入: nums = [1,3,5,6], target = 5
輸出: 2

範例 2

輸入: nums = [1,3,5,6], target = 2
輸出: 1

範例 3

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

範例 4

輸入: nums = [1,3,5,6], target = 0
輸出: 0

解法一:二分搜尋法

思路

由於數組是已經排序的,可以使用二分搜尋法來快速定位 target 應插入的位置:

  1. 設置兩個指針 leftright,初始分別為數組的開頭與結尾。
  2. 計算中間索引 mid
    • 如果 nums[mid] == target,則直接返回 mid
    • 如果 nums[mid] < target,則目標值應該在右半部分,調整 left = mid + 1
    • 如果 nums[mid] > target,則目標值應該在左半部分,調整 right = mid - 1
  3. left > right 時,left 即為目標值應插入的位置。

程式碼

class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return left

時間與空間複雜度

  • 時間複雜度:O(log n),二分搜尋法每次將搜尋範圍縮小一半。
  • 空間複雜度:O(1),只使用了常數空間。

解法二:線性掃描法

思路

直接從左到右遍歷數組,當找到第一個比 target 大的元素時,返回其索引。如果遍歷到最後都沒有找到,則目標值應插入數組末尾。此方法簡單,但不符合題目時間複雜度為 O(log n)的要求。

程式碼

class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
for i in range(len(nums)):
if nums[i] >= target:
return i
return len(nums)

時間與空間複雜度

  • 時間複雜度:O(n),需要遍歷整個數組。
  • 空間複雜度:O(1)。

解法三:內建函數

思路

Python 提供了 bisect 模組,可以直接用於查找目標值的插入位置。bisect_left 函數返回目標值的插入位置,並保證插入後數組仍然有序。

程式碼

import bisect

class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
return bisect.bisect_left(nums, target)

時間與空間複雜度

  • 時間複雜度:O(log n),bisect_left 使用二分搜索實現。
  • 空間複雜度:O(1)。

結論

  1. 最佳解法:使用 解法一(二分搜尋法),能滿足 O(log n) 的時間複雜度要求,並且實現簡潔。
  2. 次佳解法:對於小規模數據,可以使用 解法二(線性掃描法),但不適合大數據量。
  3. 內建函數解法:如果使用 Python,解法三(bisect 模組) 提供了一個簡潔的實現。

建議在實際開發中,優先採用 解法一解法三

歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
給定一個按升序排序的整數數組 nums 和一個目標值 target,請在數組中找到目標值的 第一個 和 最後一個 位置,並以一個長度為 2 的列表返回結果。如果數組中不存在目標值,返回 [-1, -1]。
給定一個按照升序排序的整數數組,但該數組可能在某個未知的軸點旋轉(例如,nums = [4,5,6,7,0,1,2])。請你在數組中搜索目標值 target,如果找到則返回其索引,否則返回 -1。
給定一個只包含 '(' 和 ')' 的字串,找出其中包含的最長的有效括號子字串的長度。
實現一個函數來重新排列數字序列,使其成為下一個更大的排列。如果不存在更大的排列,則將其排列為最小的順序(即升序)。 這個排列必須是 "原地" 完成,也就是說,只能使用常數級額外空間。
給定一個字符串 s 和一個由多個單詞組成的列表 words,請找出所有能夠在字符串 s 中連續拼接所有單詞的子字符串的起始索引。
實作一個函數 divide(dividend, divisor),計算兩個整數 dividend 和 divisor 的商,並返回其結果。
給定一個按升序排序的整數數組 nums 和一個目標值 target,請在數組中找到目標值的 第一個 和 最後一個 位置,並以一個長度為 2 的列表返回結果。如果數組中不存在目標值,返回 [-1, -1]。
給定一個按照升序排序的整數數組,但該數組可能在某個未知的軸點旋轉(例如,nums = [4,5,6,7,0,1,2])。請你在數組中搜索目標值 target,如果找到則返回其索引,否則返回 -1。
給定一個只包含 '(' 和 ')' 的字串,找出其中包含的最長的有效括號子字串的長度。
實現一個函數來重新排列數字序列,使其成為下一個更大的排列。如果不存在更大的排列,則將其排列為最小的順序(即升序)。 這個排列必須是 "原地" 完成,也就是說,只能使用常數級額外空間。
給定一個字符串 s 和一個由多個單詞組成的列表 words,請找出所有能夠在字符串 s 中連續拼接所有單詞的子字符串的起始索引。
實作一個函數 divide(dividend, divisor),計算兩個整數 dividend 和 divisor 的商,並返回其結果。
你可能也想看
Google News 追蹤
提問的內容越是清晰,強者、聰明人越能在短時間內做判斷、給出精準的建議,他們會對你產生「好印象」,認定你是「積極」的人,有機會、好人脈會不自覺地想引薦給你
Thumbnail
題目敘述 Sort Array by Increasing Frequency Leetcode #1636 給定一個輸入陣列,請依照出現頻率的多寡從低頻到高頻排列陣列元素。 如果有兩個元素的出現頻率相同,依照元素大小從大到小排列。 測試範例 Example 1: Input: nums
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
給定一個輸入非負整樹陣列nums,請找出k值,使得陣列中恰好有k個元素大於等於 k。如果無解,回傳-1。尋找k值的方法包括排序法和二分搜尋法,時間複雜度都為O(n log n),空間複雜度為O(1)。關鍵知識點是當解空間具有遞增或遞減的性質時,可以用二分搜尋法加快搜尋效率。
Thumbnail
魔鬼藏在二分搜尋裡!輸出值代表的意含、題意產生的邊界條件,寫完模板才是挑戰的開始 Orz
Thumbnail
題目已經給了依照起點升序排列好的區間陣列。 接下來新插入一個區間,插入後如果和原本的區間重疊,請把他們合併,要求我們輸出插入後的結果。 這是一個線性掃苗,所需時間為O(n)的演算法。 題目已經幫我們排序好區間順序,我們只要接著依序檢查區間、(假如有重疊的話)合併區間。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們兩個字串。 第一個是指定順序的字串order。 第二個是輸入字串s。 要求我們依據order給定的順序,重新排列s。 如果出現order中沒有出現的字母,任意位置皆可。 合法答案可能不只一組,輸出其中一種即可。 題目的原文敘述 測試範例 Example
Thumbnail
題目敘述 題目會給定我們一個整數陣列nums,要求我們把裡面的0做元素交換,把0都搬到陣列的右邊。題目要求必須in-place在原本的陣列裡面做操作,不可以額外建立新的陣列。 題目的原文敘述 測試範例 Example 1: Input: nums = [0,1,0,3,12] Outpu
Thumbnail
題目敘述 題目會給兩個陣列nums1和nums2。 題目要求我們從中同步選擇長度為k的子序列,並且最大化子序列的分數, 回傳最高的分數值。 分數的定義: 分數 = (nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] ,
提問的內容越是清晰,強者、聰明人越能在短時間內做判斷、給出精準的建議,他們會對你產生「好印象」,認定你是「積極」的人,有機會、好人脈會不自覺地想引薦給你
Thumbnail
題目敘述 Sort Array by Increasing Frequency Leetcode #1636 給定一個輸入陣列,請依照出現頻率的多寡從低頻到高頻排列陣列元素。 如果有兩個元素的出現頻率相同,依照元素大小從大到小排列。 測試範例 Example 1: Input: nums
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
給定一個輸入非負整樹陣列nums,請找出k值,使得陣列中恰好有k個元素大於等於 k。如果無解,回傳-1。尋找k值的方法包括排序法和二分搜尋法,時間複雜度都為O(n log n),空間複雜度為O(1)。關鍵知識點是當解空間具有遞增或遞減的性質時,可以用二分搜尋法加快搜尋效率。
Thumbnail
魔鬼藏在二分搜尋裡!輸出值代表的意含、題意產生的邊界條件,寫完模板才是挑戰的開始 Orz
Thumbnail
題目已經給了依照起點升序排列好的區間陣列。 接下來新插入一個區間,插入後如果和原本的區間重疊,請把他們合併,要求我們輸出插入後的結果。 這是一個線性掃苗,所需時間為O(n)的演算法。 題目已經幫我們排序好區間順序,我們只要接著依序檢查區間、(假如有重疊的話)合併區間。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們兩個字串。 第一個是指定順序的字串order。 第二個是輸入字串s。 要求我們依據order給定的順序,重新排列s。 如果出現order中沒有出現的字母,任意位置皆可。 合法答案可能不只一組,輸出其中一種即可。 題目的原文敘述 測試範例 Example
Thumbnail
題目敘述 題目會給定我們一個整數陣列nums,要求我們把裡面的0做元素交換,把0都搬到陣列的右邊。題目要求必須in-place在原本的陣列裡面做操作,不可以額外建立新的陣列。 題目的原文敘述 測試範例 Example 1: Input: nums = [0,1,0,3,12] Outpu
Thumbnail
題目敘述 題目會給兩個陣列nums1和nums2。 題目要求我們從中同步選擇長度為k的子序列,並且最大化子序列的分數, 回傳最高的分數值。 分數的定義: 分數 = (nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] ,