LeetCode 4 尋找兩個有序陣列的中位數

2021-10-03 07:25:22 字數 2218 閱讀 2716

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。

請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o(log(m + n))。

你可以假設 nums1 和 nums2 不會同時為空。

示例 1:

nums1 = [1, 3]

nums2 = [2]

則中位數是 2.0

示例 2:

nums1 = [1, 2]

nums2 = [3, 4]

則中位數是 (2 + 3)/2 = 2.5

這道題如果沒有時間複雜度的要求會變得很簡單,把兩個陣列合併起來排序就好。我最開始的想法也是排序,但是並沒有排序的方法可以達到log級別的複雜度。而結合題目中有序陣列這樣的條件,想要達到logn級別的複雜度應該使用二分法查詢。

這道題讓我們求兩個有序陣列的中位數,而且限制了時間複雜度為o(log (m+n)),看到這個時間複雜度,自然而然的想到了應該使用二分查詢法來求解。那麼回顧一下中位數的定義,如果某個有序陣列長度是奇數,那麼其中位數就是最中間那個,如果是偶數,那麼就是最中間兩個數字的平均值。這裡對於兩個有序陣列也是一樣的,假設兩個有序陣列的長度分別為m和n,由於兩個陣列長度之和 m+n 的奇偶不確定,因此需要分情況來討論,對於奇數的情況,直接找到最中間的數即可,偶數的話需要求最中間兩個數的平均值。為了簡化**,不分情況討論,我們使用乙個小trick,我們分別找第 (m+n+1) / 2 個,和 (m+n+2) / 2 個,然後求其平均值即可,這對奇偶數均適用。加入 m+n 為奇數的話,那麼其實 (m+n+1) / 2 和 (m+n+2) / 2 的值相等,相當於兩個相同的數字相加再除以2,還是其本身。

這裡我們需要定義乙個函式來在兩個有序陣列中找到第k個元素,下面重點來看如何實現找到第k個元素。首先,為了避免產生新的陣列從而增加時間複雜度,我們使用兩個變數i和j分別來標記陣列nums1和nums2的起始位置。然後來處理一些邊界問題,比如當某乙個陣列的起始位置大於等於其陣列長度時,說明其所有數字均已經被淘汰了,相當於乙個空陣列了,那麼實際上就變成了在另乙個陣列中找數字,直接就可以找出來了。還有就是如果k=1的話,那麼我們只要比較nums1和nums2的起始位置i和j上的數字就可以了。難點就在於一般的情況怎麼處理?因為我們需要在兩個有序陣列中找到第k個元素,為了加快搜尋的速度,我們要使用二分法,對k二分,意思是我們需要分別在nums1和nums2中查詢第k/2個元素,注意這裡由於兩個陣列的長度不定,所以有可能某個陣列沒有第k/2個數字,所以我們需要先檢查一下,陣列中到底存不存在第k/2個數字,如果存在就取出來,否則就賦值上乙個整型最大值。如果某個陣列沒有第k/2個數字,那麼我們就淘汰另乙個數字的前k/2個數字即可。有沒有可能兩個陣列都不存在第k/2個數字呢,這道題裡是不可能的,因為我們的k不是任意給的,而是給的m+n的中間值,所以必定至少會有乙個陣列是存在第k/2個數字的。最後就是二分法的核心啦,比較這兩個陣列的第k/2小的數字midval1和midval2的大小,如果第乙個陣列的第k/2個數字小的話,那麼說明我們要找的數字肯定不在nums1中的前k/2個數字,所以我們可以將其淘汰,將nums1的起始位置向後移動k/2個,並且此時的k也自減去k/2,呼叫遞迴。反之,我們淘汰nums2中的前k/2個數字,並將nums2的起始位置向後移動k/2個,並且此時的k也自減去k/2,呼叫遞迴即可。

class

solution

//i: nums1的起始位置 j: nums2的起始位置

public

intfindkth

(int

nums1,

int i,

int[

] nums2,

int j,

int k)

int midval1 =

(i + k /2-

1< nums1.length)

? nums1[i + k /2-

1]: integer.max_value;

int midval2 =

(j + k /2-

1< nums2.length)

? nums2[j + k /2-

1]: integer.max_value;

if(midval1 < midval2)

else

}}

需要理解的事情是為什麼賦值int_max。假設在查詢第k/2時,有乙個陣列(nums1)已經超過了length

這個演算法的執行時間並不是很快,可能是遞迴演算法比較慢導致的。

LeetCode 4 尋找兩個有序陣列的中位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不會同時為空。示例 1 nums1 1,3 nums2 2 則中位數是 2.0 示例 2 nums1 1,2 ...

LeetCode 4 尋找兩個有序陣列的中位數

給定兩個大小為 m 和 n 的有序陣列nums1和nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設nums1和nums2不會同時為空。示例 1 nums1 1,3 nums2 2 則中位數是 2.0示例 2 nums1 1,2 nums2 3,...

LeetCode4 尋找兩個有序陣列的中位數

給定兩個大小為 m 和 n 的有序陣列nums1和nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設nums1和nums2不會同時為空。示例 1 nums1 1,3 nums2 2 則中位數是 2.0示例 2 nums1 1,2 nums2 3,...