1. 程式人生 > >LeetCode 4

LeetCode 4

vector public 一段 個數 ans con top 定位 and

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 median 
is 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