leetcode4_尋找兩個有序數組的中位數

1. 在統計中,中位數被用來:

將一個集合劃分爲兩個長度相等的子集,其中一個子集中的元素總是大於另一個子集中的元素。

2. 解法1

簡單粗暴,先將兩個數組合並,兩個有序數組的合併也是歸併排序中的一部分。然後根據奇數,還是偶數,返回中位數。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        vector<int> num(m+n);
        int s1=0, s2=0, k=0;
        while(s1!=m && s2!=n) {
            if(nums1[s1]<=nums2[s2]) num[k++] = nums1[s1++];
            else num[k++] = nums2[s2++];
        }
        while(s1!=m) {
            num[k++] = nums1[s1++];
        }
        while(s2!=n) {
            num[k++] = nums2[s2++];
        }
        if(((m+n)&1)==0) return (num[(m+n)/2]+num[(m+n)/2-1])/2.0;
        else return num[(m+n)/2]*1.0;
    }
};

時間複雜度:遍歷全部數組 (m+n)

空間複雜度:開闢了一個數組,保存合併後的兩個數組 O(m+n)

3. 解法二

1. 其實,我們不需要將兩個數組真的合併,我們只需要找到中位數在哪裏就可以了。

2. 題目是求中位數,其實就是求第 k 小數的一種特殊情況,而求第 k 小數有一種算法。

class Solution {
public:
    int getK(vector<int>& nums1,int s1,int e1,vector<int>& nums2,int s2,int e2,int k) {
        int len1 = e1-s1+1, len2 = e2-s2+1;
        if(len1>len2) return getK(nums2,s2,e2,nums1,s1,e1,k);
        if(len1==0) return nums2[s2+k-1];
        if(k==1) return nums1[s1]>nums2[s2] ? nums2[s2]:nums1[s1];
        int i = s1+min(len1,k/2)-1;
        int j = s2+min(len2,k/2)-1;
        if(nums1[i]>nums2[j]) return getK(nums1,s1,e1,nums2,j+1,e2,k-(j-s2+1));
        else return getK(nums1,i+1,e1,nums2,s2,e2,k-(i-s1+1));
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        int left = (m+n+1)/2;
        int right = (m+n+2)/2;
        return (getK(nums1,0,m-1,nums2,0,n-1,left) + 
               getK(nums1,0,m-1,nums2,0,n-1,right))/2.0;
    }
};

時間複雜度:每進行一次循環,我們就減少 k/2 個元素,所以時間複雜度是 O(log(k),而 k=(m+n)/2,所以最終的複雜也就是 O(log(m+n))。

空間複雜度:雖然我們用到了遞歸,但是可以看到這個遞歸屬於尾遞歸,所以編譯器不需要不停地堆棧,所以空間複雜度爲 O(1)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章