[LeetCode解題攻略] 4. Median of Two Sorted Arrays

更新於 2024/12/04閱讀時間約 8 分鐘

題目描述

給定兩個已排序的陣列 nums1nums2,請找到並返回這兩個陣列的中位數。要求時間複雜度為 O(log(min(m, n))),其中 mn 分別是兩個陣列的長度。

範例:

  • 輸入:nums1 = [1, 3], nums2 = [2]
    輸出:2.0
  • 輸入:nums1 = [1, 2], nums2 = [3, 4]
    輸出:2.5

解題思路

中位數問題在兩個已排序陣列中可以透過二分搜尋來解決。為了達成 O(log(min(m, n))) 的時間複雜度要求,我們可以在較短的陣列中進行二分搜尋,從而縮小運算範圍。

思路概述:

  1. 分割陣列:將兩個陣列視為一整體,分割成兩部分,使得左邊部分的數量等於右邊部分。
  2. 選擇左側最大值右側最小值:中位數即是左側最大值和右側最小值的平均數或其中一個。
  3. 二分搜尋優化:在較短的陣列中進行分割調整,直至找到合適的分割點,使得左側的數字都小於右側。

解法一:二分搜尋

在這裡,我們以較短的陣列進行二分搜尋。透過在 nums1 中調整分割點,可以計算出 nums2 中相應的分割位置,並驗證是否滿足條件。最終的分割結果即為中位數。

步驟詳解:

  1. 確保 nums1 是較短的陣列(如果不是,交換 nums1nums2)。
  2. 設置 lowhighnums1 的左右邊界。
  3. nums1 中進行二分搜尋,計算分割點 partition1partition2
  4. 確認條件:
    • nums1[partition1 - 1] <= nums2[partition2]nums2[partition2 - 1] <= nums1[partition1],則找到合適的分割點。
  5. 計算中位數:
    • 若兩陣列總長度為奇數,則中位數為左側最大值。
    • 若總長度為偶數,中位數為左側最大值與右側最小值的平均。

程式碼實現:

class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
# 確保 nums1 是較短的陣列
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1

m, n = len(nums1), len(nums2)
low, high = 0, m

while low <= high:
partition1 = (low + high) // 2
partition2 = (m + n + 1) // 2 - partition1

# 邊界情况
max_left1 = float('-inf') if partition1 == 0 else nums1[partition1 - 1]
min_right1 = float('inf') if partition1 == m else nums1[partition1]
max_left2 = float('-inf') if partition2 == 0 else nums2[partition2 - 1]
min_right2 = float('inf') if partition2 == n else nums2[partition2]

if max_left1 <= min_right2 and max_left2 <= min_right1:
if (m + n) % 2 == 0:
return (max(max_left1, max_left2) + min(min_right1, min_right2)) / 2
else:
return max(max_left1, max_left2)
elif max_left1 > min_right2:
high = partition1 - 1
else:
low = partition1 + 1
  • 時間複雜度O(log(min(m, n))),因為我們在較短的陣列中進行二分搜尋。
  • 空間複雜度O(1),僅使用常數空間來存儲指標和變量。

解法二:合併排序法

另一種解法是合併兩個排序陣列,但這種解法的時間複雜度為 O(m + n),不符合題目要求的 O(log(min(m, n)))。儘管如此,若不考慮時間限制,這種方法對理解中位數概念有幫助。

步驟詳解:

  1. 將兩個陣列合併。
  2. 將合併過後的陣列排序。
  3. 如果合併過後長度為奇數,返回中間值;若為偶數,返回兩個中間值的平均數。

程式碼實現:

class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
list_combined = []

# 合併兩個陣列
list_combined = nums1 + nums2

# 排序陣列
list_combined.sort()

# 計算中位數
if len(list_combined) % 2 == 0:
return (list_combined[int(len(list_combined) * 0.5) - 1] + list_combined[int(len(list_combined) * 0.5)]) / 2.0
else:
return list_combined[floor(len(list_combined) * 0.5)]
  • 時間複雜度O(m + n),因為需要遍歷兩個陣列並將所有元素合併到一個新陣列中。
  • 空間複雜度O(m + n),因為使用了額外的空間來儲存合併的陣列。

小結

這道題主要測試二分搜尋在數組合併與排序中的應用。解法一通過較短陣列的二分搜尋,巧妙地達到 O(log(min(m, n))) 的時間複雜度,是處理中位數問題的最優解法。


歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
給定一個字串 s,請找出其中不含重複字母的最長子字串的長度。
在這篇文章中,我們將深入探討 LeetCode 題目「2. Add Two Numbers」的解法。這道題目考察對鏈結串列 (Linked List) 操作和進位處理的掌握。
在 LeetCode 上,Two Sum 這道題目主要考察如何高效地處理數組和數據查找問題,是面試中常見的問題之一。今天我們將詳細解說這道題目,並提供幾種解題方法。
給定一個字串 s,請找出其中不含重複字母的最長子字串的長度。
在這篇文章中,我們將深入探討 LeetCode 題目「2. Add Two Numbers」的解法。這道題目考察對鏈結串列 (Linked List) 操作和進位處理的掌握。
在 LeetCode 上,Two Sum 這道題目主要考察如何高效地處理數組和數據查找問題,是面試中常見的問題之一。今天我們將詳細解說這道題目,並提供幾種解題方法。
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
題目敘述 Find K-th Smallest Pair Distance 給定一個輸入陣列nums和 參數k。 請找出第k小的pair distance是多少? pair distance定義為 abs( nums[i] - nums[j]), i 不等於j 也就是任意兩陣列元素差值的絕對值
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Make Two Arrays Equal by Reversing Subarrays 題目給定兩個輸入陣列,請問能否透過子陣列的反轉讓兩個陣列相等? 子陣列的反轉操作次數不受限制。 如果可以,返回True 如果不行,返回False
Thumbnail
題目敘述 Sort Array by Increasing Frequency Leetcode #1636 給定一個輸入陣列,請依照出現頻率的多寡從低頻到高頻排列陣列元素。 如果有兩個元素的出現頻率相同,依照元素大小從大到小排列。 測試範例 Example 1: Input: nums
Thumbnail
給定兩個輸入陣列,第一個陣列代表每個人的姓名,第二個陣列代表每個人的身高。依照身高從高到矮進行排列,輸出每個人的名字。本文介紹了一個根據身高排列人名的算法,並提供了相關的程式碼和時間複雜度分析。
Thumbnail
題目敘述 Intersection of Two Arrays II 給定兩個輸入陣列,請找出兩個陣列交集的元素,並且依照出現次數輸出。 測試範例 Example 1: Input: nums1 = [1,2,2,1], nums2 = [2,2] Output: [2,2] 交集元素
Thumbnail
題目敘述 Longest Arithmetic Subsequence of Given Difference 給定一個整數陣列nums,請找出給定公差difference的最長的等差數列的長度是多少?
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
題目敘述 Find K-th Smallest Pair Distance 給定一個輸入陣列nums和 參數k。 請找出第k小的pair distance是多少? pair distance定義為 abs( nums[i] - nums[j]), i 不等於j 也就是任意兩陣列元素差值的絕對值
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Make Two Arrays Equal by Reversing Subarrays 題目給定兩個輸入陣列,請問能否透過子陣列的反轉讓兩個陣列相等? 子陣列的反轉操作次數不受限制。 如果可以,返回True 如果不行,返回False
Thumbnail
題目敘述 Sort Array by Increasing Frequency Leetcode #1636 給定一個輸入陣列,請依照出現頻率的多寡從低頻到高頻排列陣列元素。 如果有兩個元素的出現頻率相同,依照元素大小從大到小排列。 測試範例 Example 1: Input: nums
Thumbnail
給定兩個輸入陣列,第一個陣列代表每個人的姓名,第二個陣列代表每個人的身高。依照身高從高到矮進行排列,輸出每個人的名字。本文介紹了一個根據身高排列人名的算法,並提供了相關的程式碼和時間複雜度分析。
Thumbnail
題目敘述 Intersection of Two Arrays II 給定兩個輸入陣列,請找出兩個陣列交集的元素,並且依照出現次數輸出。 測試範例 Example 1: Input: nums1 = [1,2,2,1], nums2 = [2,2] Output: [2,2] 交集元素
Thumbnail
題目敘述 Longest Arithmetic Subsequence of Given Difference 給定一個整數陣列nums,請找出給定公差difference的最長的等差數列的長度是多少?
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學