1. 程式人生 > 其它 >力扣刷題:4. 尋找兩個正序陣列的中位數

力扣刷題:4. 尋找兩個正序陣列的中位數

技術標籤:leetcode演算法c++排序演算法資料結構

題目要求

給定兩個大小為 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;
分母變成浮點數,除法自動轉換為浮點數除法。