LeetCode 4
Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3] nums2 = [2] The medianis 2.0
Solution:
static const auto speedup = [](){ ios::sync_with_stdio(false); cin.tie(nullptr); return nullptr; }(); class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int l1 = nums1.size(), l2 = nums2.size();if (l1 > l2){ vector<int> temp = nums1; nums1 = nums2; nums2 = temp; int temp_num = l1; l1 = l2; l2 = temp_num; } int iMax = l1, iMin = 0, h = (l1 + l2 + 1) / 2, i = 0, j = 0; while (iMin <= iMax){ i = (iMax + iMin) / 2, j = h - i;if (i > iMin && nums1[i-1] > nums2[j]){ iMax = i - 1; }else if (i < iMax && nums2[j-1] > nums1[i]){ iMin = i + 1; }else{ int left = 0, right = 0; if (i == 0){ left = nums2[j-1]; }else if (j == 0){ left = nums1[i-1]; }else{ left = nums1[i-1] > nums2[j-1] ? nums1[i-1] : nums2[j-1]; } if ((l1 + l2) % 2 == 1){ return left; } if (i == l1){ right = nums2[j]; }else if (j == l2){ right = nums1[i]; }else{ right = nums1[i] < nums2[j] ? nums1[i] : nums2[j]; } return (left + right) / 2.0; } } return 0; } };
1. 思路簡述
整體的思路是二分查找。首先假設數組A是較短的那個數組,數組B是較長的那個數組,我們要找的是這兩個數組的分割點i j,分割點要滿足如下幾個因素:
1. 分割點左邊兩數組的任意元素均小於分割點右邊兩數組的任意元素
2. 分割點左邊的元素的個數之和等於右邊的元素個數之和: j = (l1 + l2 + 1) / 2 - i .
所以:
1. 按照首先二分定位A的中間點作為i,計算j
2.查看i是否符合要求
2.1 如不符合要求則更新iMax或iMin進行下一次二分
2.2 如果符合要求,計算left和right
2.2.1 left為數組兩部分左邊的最大值。當i == 0時(A整個數組都大於B,整個A放在右半邊)left == B[j-1];當j == 0時(B整個數組都大於A)left == A[i-1];正常情況下,選出left == max(A[i-1], B[j-1])。在這裏,如果(l1 + l2) % 2 == 1,程序結束,返回left。
2.2.2 right為數組兩部分右邊的最小值。當i == l1時(A整個數組都小於B,整個A放在左半邊)right == B[j];當j == l2時(B整個數組都小於A)right == A[i];正常情況下,選出right == min(A[i], B[j])
2. 改進方式
2.1 速度改進
static const auto speedup = [](){ ios::sync_with_stdio(false); cin.tie(nullptr); return nullptr; }();
加入這一段代碼可以讓代碼提速很多(From Top70% to Top30%),原因是:
std::ios::sync_with_stdio(false);
這個函數是一個“是否兼容stdio”的開關,C++為了兼容C,保證程序在使用了std::printf和std::cout的時候不發生混亂,將輸出流綁到了一起。
cin,cout之所以效率低,是因為先把要輸出的東西存入緩沖區,再輸出,導致效率降低,而這段語句可以來打消iostream的輸入 輸出緩存,可以節省許多時間,使效率與scanf與printf相差無幾,還有應註意的是scanf與printf使用的頭文件應是stdio.h而不是 iostream。
cin.tie(nullptr);
tie是將兩個stream綁定的函數,空參數的話返回當前的輸出流指針。
PS. NULL & nullptr
在C++中指針必須有明確的類型定義。但是將NULL定義為0帶來的另一個問題是無法與整數的零區分。因為C++中允許有函數重載,所以可以試想如下函數定義情況:
void func(int data); void func(char* data);
那麽在傳入NULL參數時,編譯器將無法確定到底使用哪個函數定義,造成編譯時錯誤。nullptr在C++11被引入用於解決這一問題,nullptr可以明確區分整型和指針類型,能夠根據環境自動轉換成相應的指針類型,但不會被轉換為任何整型,所以不會造成參數傳遞錯誤。
2.2 某一種寫法
if(nums1.size() < nums2.size()) { return findMedianSortedArrays(nums2, nums1); }
LeetCode 4