【Leetcode】尋找兩個有序數組的中位數

 

使用二分法搜尋合適的i值,計算對應的j值,最後經過分類討論nums1和nums2的多種狀況計算獲得中值。數組

二分法的關鍵思想是   假設該數組的長度是N那麼二分後是N/2,再二分後是N/4……直到二分到1結束(固然這是屬於最壞的狀況了,即每次找到的那個中點數都不是咱們要找的),那麼二分的次數就是基本語句執行的次數,因而咱們能夠設次數爲x,N*(1/2)^x=1;則x=logn,底數是2。學習

所以,該問題的時間複雜度是 O(log(min(m,n)).spa

空間複雜度 O(m+n)code

執行用時 :  300ms, 在Median of Two Sorted Arrays的C++提交中擊敗了7.57% 的用戶
內存消耗 :  11 MB, 在Median of Two Sorted Arrays的C++提交中擊敗了77.28% 的用戶
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        double ans;
        int len1 = nums1.size();
        int len2 = nums2.size();
        if (len1 > len2){
            vector<int> temp(nums1);
            nums1 = nums2;
            nums2 = temp;
            len1 = nums1.size();
            len2 = nums2.size();
        }
        
        // if nums1 is empty 
        if (len1 == 0){
            if (len2 % 2 == 0)
                return ans = 0.5*(nums2[len2/2 - 1] + nums2[len2/2]);
            else
                return ans = nums2[int(len2/2)];
        }
        
        int i = 0, j = 0;
        int imin = 0, imax = len1; // 這兩個變量用於二分法
        
        while(imin <= imax){  // 二分法的開展條件
            i = int(0.5*(imin+imax));
            j = getValueJ(len1,len2,i);
            
            if(i==0 || j==len2 || nums1[i-1] <= nums2[j]){
                if(i==len1 || j==0 || nums1[i] >= nums2[j-1]){
                    ans = getMedian(nums1, nums2, len1, len2, i, j);
                    break;
                }
                else{
                    imin = i+1;
                    cout << "imin : " << imin << endl;
                }
            }
            else{
                imax = i;
            }
        }
        return ans;
    }
    
    int getValueJ(int len1, int len2, int iIndex){
        int jIndex;
        if ((len1+len2) % 2 == 0)
            jIndex = 0.5*(len1+len2) - iIndex;
        else
            jIndex = 0.5*(len1+len2+1) - iIndex;
        
        return jIndex;
    }
    
    double getMedian(vector<int> &num1, vector<int> &num2, int len1, int len2, int iIndex, int jIndex){
        
        /*********
        for (int i = 0; i < len1; i++)
            cout << num1[i] << " ";
        cout << endl;
        for (int j = 0; j < len2; j++)
            cout << num2[j] << " ";
        cout << endl;
        
        cout << "iIndex : "<< iIndex << endl;
        cout << "jIndex : "<< jIndex << endl;
        
        cout << "len1 : " << len1 << endl;
        cout << "len2 : " << len2 << endl;
        **********/        

        double median;
        vector<int> leftP, rightP;
        
        if ((len1+len2) % 2 ){
            cout << "the sum of two vector is odd number" << endl;
            
            // we know that size of vector leftP is bigger than that of vector rightP
            if (iIndex > 0 && jIndex > 0){
                vector<int> tmp;
                for (int i = 0; i < iIndex; i++)
                    tmp.push_back(num1[i]);
                for (int j = 0; j < jIndex; j++)
                    tmp.push_back(num2[j]);
                median =  *max_element(tmp.begin(), tmp.end());
            }
            else if (iIndex == 0)
                median = *max_element(num2.begin(), (num2.end()-(len2-jIndex)));
            else if (jIndex == 0)
                median = *max_element(num1.begin(), (num1.end()-(len1-iIndex)));

        }
        
        else{
            cout << "the sum of two vector is even number" << endl;
            
            if (iIndex == 0){
                leftP.clear();
                rightP.clear();
                for (int j = 0; j < jIndex; j++){
                    leftP.push_back(num2[j]);
                }
                
                rightP = num1;
                if(jIndex < len2)
                    for(int j = jIndex; j < len2; j++)
                        rightP.push_back(num2[j]);
                
                /**************
                cout << "leftP : ";
                for(int i = 0; i < leftP.size(); i++)
                    cout << leftP[i] << " ";
                cout << endl << "rightP : ";
                for(int j = 0; j < rightP.size(); j++)
                    cout << rightP[j] << "";
                cout << endl;
                **************/
            }
            
            else if (iIndex == len1){
                leftP.clear();
                rightP.clear();
                leftP = num1;
                if (jIndex > 0 && jIndex < len2)
                    for (int j = 0; j < jIndex; j++)
                        leftP.push_back(num2[j]);
                
                for (int j = jIndex; j < len2; j++)
                    rightP.push_back(num2[j]);
            }
            
            else{
                leftP.clear();
                rightP.clear();
                for (int i = 0; i < iIndex; i++)
                    leftP.push_back(num1[i]);
                
                if(jIndex > 0){
                    for(int j = 0; j < jIndex; j++)
                        leftP.push_back(num2[j]);
                }
                
                for(int i = iIndex; i < len1; i++)
                    rightP.push_back(num1[i]);
                
                if(jIndex < len2)
                    for(int j = jIndex; j < len2; j++)
                        rightP.push_back(num2[j]);
            }
            
            int leftV =  *max_element(leftP.begin(), leftP.end());
            int rightV = *min_element(rightP.begin(), rightP.end());
            cout << "leftV : " << leftV << "  " << "rightV : " << rightV << endl;
            median = 0.5*(leftV+rightV);                        
        }
        return median;
    }
};

 

nums1和nums2都是按升序排列,其長度size = m+n。將前 size/2+1(size爲偶數) 或 (size+1)/2(size爲奇數) 進行排序,便可找到中位數。blog

Tip: 學習迭代器的使用,迭代器的增加;排序

執行用時 :  32 ms, 在Median of Two Sorted Arrays的C++提交中擊敗了98.57% 的用戶
內存消耗 :  9.7 MB, 在Median of Two Sorted Arrays的C++提交中擊敗了87.28% 的用戶
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        
        auto left = nums1.begin();
        auto right = nums2.begin();
        int size = nums1.size() + nums2.size();
        //int sum = 0;
        int temp = 0; 
        int temp1 = 0;
        for (int i = 0; i <= size / 2; i++)
        {    
            if (left == nums1.end())
                temp = *right++;
            else if (right == nums2.end())
                temp = *left++;
            else if (*left < *right)
                temp = *left++;
            else
                temp = *right++;
            if (size / 2 - 1 == i)
            {
                temp1 = temp;
            }
        }
        if (size % 2 != 0)
        {
            return temp;
        }
        else
        {
            return (temp + temp1) / 2.0;
        }

    }
};
相關文章
相關標籤/搜索