力扣刷題:4. 尋找兩個正序陣列的中位數
題目要求
給定兩個大小為 m 和 n 的正序(從小到大)陣列 nums1 和 nums2。請你找出並返回這兩個正序陣列的中位數。
進階:你能設計一個時間複雜度為 O(log (m+n)) 的演算法解決此問題嗎?
題目連結
版本一:直接呼叫庫函式
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
auto backInsert = std::back_inserter(nums1);
std::copy(nums2.cbegin(), nums2.cend(), backInsert);
std::sort(nums1.begin(), nums1.end());
if (nums1.size() % 2 == 1)
{
return nums1[nums1.size() / 2];
}
else
{
return (nums1[nums1.size() / 2] + nums1[nums1.size() / 2 - 1]) / 2.0;
}
}
};
(這個版本不符合考察要求,需要手工實現更加底層的操作)
學到了什麼
1、熟悉了泛型演算法sort的用法:傳入兩個迭代器,然後該演算法會對迭代器範圍內的數按照預設<進行排序
2、sort定義在標頭檔案algorithm裡面
3、熟悉了泛型演算法copy的用法:傳入兩個迭代器和一個起始位置迭代器。將前兩個迭代器指定範圍內的數拷貝到以第三個迭代器起始的位置。預設第三個位置空間充足。
版本二:從底層做起
class Solution {
public:
double findMedianSortedArrays (vector<int>& nums1, vector<int>& nums2) {
for (auto i : nums2)
nums1.push_back(i);
vector<int> temp(nums1.size(), 0);
mysort(nums1, 0, nums1.size() - 1, temp);
if (nums1.size() % 2 != 0)
{
return nums1[nums1.size() / 2];
}
else
{
return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2.0;
}
}
void mysort(vector<int>& v, unsigned left, unsigned right, vector<int>& temp)
{
if (left < right)
{
unsigned mid = (left + right) / 2;
mysort(v, left, mid, temp);
mysort(v, mid + 1, right, temp);
mymerge(v, left, mid, right, temp);
}
}
void mymerge(vector<int>& v, unsigned left, unsigned mid, unsigned right, vector<int>& temp)
{
unsigned l = left, r = mid+1, t = 0;
while (l <= mid && r <= right)
{
if (v[l] <= v[r])
{
temp[t++] = v[l++];
}
else
{
temp[t++] = v[r++];
}
}
while (l <= mid)
{
temp[t++] = v[l++];
}
while (r <= right)
{
temp[t++] = v[r++];
}
t = 0;
while (left <= right)
{
v[left++] = temp[t++];
}
}
};
學會了什麼
1、學會了自己寫一個歸併排序。歸併排序主要分為兩部分,分和治。本題中,“分”通過mysort函式實現,遞迴呼叫了兩次mysort函式,一次排序左邊序列,一次排序右邊序列。
這裡的分並沒有在實體記憶體上將容器中的資料進行切分,而是通過遞迴函式傳遞不同的left和right邊界實現邏輯上的遞迴。
“治”通過mymerge函式實現,在呼叫完兩次mysort函式,將左右兩邊都排好序後,呼叫mymerge函式。
在邏輯上切分好後,便通過傳遞進來的left、mid、right界定左右兩個界限。傳入的容器引用可以實現實際上物理儲存資料的改變。而傳入的temp容器引用則是為了避免遞迴中頻繁開闢空間。
2、關於int和double進行除法的問題
return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2;
返回的是int,小數部分被截斷了,這裡踩了一次坑
return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2.0;
分母變成浮點數,除法自動轉換為浮點數除法。