1.題目描述
給定兩個大小分別為m
和n
的正序(從小到大)陣列nums1
和nums2
。請你找出並返回這兩個正序陣列的 中位數 。
2.示例
示例 1:
輸入:nums1 = [1,3], nums2 = [2]示例 2:輸出:2.00000
解釋:合併陣列 = [1,2,3] ,中位數 2
輸入:nums1 = [0,0], nums2 = [0,0]示例 3:輸出:0.00000
輸入:nums1 = [1,2], nums2 = [3,4]
輸出:2.50000
解釋:合併陣列 = [1,2,3,4] ,中位數 (2 + 3) / 2 = 2.5
3.分析
此題難度不大,有如下思路
(1)最簡單的想法是,將一個陣列的每一個元素,按照升序通過插入法等方法將兩個陣列合並。然後根據奇偶性質找出中位數的位置並計算。
但是這種方法不是高效的,空間上它需要重新申請一個m+n長度的新陣列。至少也需要將較短的那個陣列重新申請空間到較長的那個陣列上。
時間上,由於每次需要將一個元素有序插入到另一個陣列中,時間也會有較大的浪費。
(2)根據上面的方法,時間浪費的原因在於沒有利用好兩個陣列已經有序的條件。改進的方法,不再將兩個陣列和並,也不關心中位數之後的元素
的排序。通過兩個陣列的元素和計算出中位數的位置,設定指向兩個陣列的兩個遊標進行移動。在兩個陣列的元素都沒被遍歷完時,比較當前兩個遊標對應的元素大小,使較小元素的遊標後移。
在某一個陣列已經被比較完時,則將另一個陣列的元素順序不動遍歷即可,直到整體的遊標數到達中位數的位置。
這樣就提高了時間和空間的效率,類似流的不儲存元素的值,只關心中位數的位置。達到了空間複雜度為o(m+n)
4.**
classsolution
else
if(numpos1;
else numpos2++;
counter++;
}if(numpos1nums2.size())
else
if(numpos1nums1.at(numpos1);
else result+=nums2.at(numpos2);
}else
else
if(numpos1;
else numpos2++;
counter++;
}for(int i=0;i<2;i++)
else
}else
if(numpos1;}
else
}result =result/2
; }
return
result;
}};
5.總結
(1)上述**不夠優雅,原因是一開始就將奇偶分開處理,導致有很大程度的重複**。
(2)這也說明了這個題的細節問題:即對奇偶元素個數的遊標位置的處理細節。