1. 程式人生 > 其它 >leetcode 4 兩個正序陣列中位數

leetcode 4 兩個正序陣列中位數

普通方法,就算總的數個數,然後通過雙指標的方法訪問陣列中的元素,可以搞出來,但是時間複雜度不是log的,先貼下程式碼

  1 class Solution {
  2 public:
  3     double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) 
  4     {
  5         int n1 = nums1.size();
  6         int n2 = nums2.size();
  7         int n = nums1.size() + nums2.size();
8 double res = 0; 9 if(n%2 == 0) // 整除2 10 { 11 int k1 = n/2; 12 int k2 = n/2+1; 13 int l = 0; 14 int i = -1; 15 int j = -1; 16 while(l+1 < k1) // 未找到中位數的所在位置 17 { 18 if(i+1
<n1 && j+1<n2) 19 { 20 if(nums1[i+1]<=nums2[j+1]) //較小的為下一個 21 { 22 i++; 23 l++; 24 } 25 else 26 { 27 j++;
28 l++; 29 } 30 } 31 else if(i+1 < n1) 32 { 33 i++; 34 l++; 35 } 36 else if(j+1 < n2) 37 { 38 j++; 39 l++; 40 } 41 } 42 //找到位置 43 for(int t = 0 ; t <= 1 ; t++) 44 { 45 if(i+1<n1 && j+1<n2) 46 { 47 if(nums1[i+1]<=nums2[j+1]) //較小的為下一個 48 { 49 res+=nums1[i+1]; 50 i++; 51 l++; 52 } 53 else 54 { 55 res+=nums2[j+1]; 56 j++; 57 l++; 58 } 59 } 60 else if(i+1 < n1) 61 { 62 res+=nums1[i+1]; 63 i++; 64 l++; 65 } 66 else if(j+1 < n2) 67 { 68 res+=nums2[j+1]; 69 j++; 70 l++; 71 } 72 } 73 return res/2; 74 } 75 else 76 { 77 if(n == 1) 78 { 79 if(nums1.size()) 80 return nums1[0]; 81 else 82 return nums2[0]; 83 } 84 int k = (n+1)/2; 85 int l = 0; 86 int i = -1; 87 int j = -1; 88 // 未找到中位數的所在位置 89 while(l+1 < k) 90 { 91 if(i+1<n1 && j+1<n2) 92 { 93 if(nums1[i+1]<=nums2[j+1]) //較小的為下一個 94 { 95 i++; 96 l++; 97 } 98 else 99 { 100 j++; 101 l++; 102 } 103 } 104 else if(i+1 < n1) 105 { 106 i++; 107 l++; 108 } 109 else if(j+1 < n2) 110 { 111 j++; 112 l++; 113 } 114 } 115 //找到位置 116 if(i+1<n1 && j+1<n2) 117 { 118 if(nums1[i+1]<=nums2[j+1]) //較小的為下一個 119 { 120 res=nums1[i+1]; 121 i++; 122 l++; 123 } 124 else 125 { 126 res=nums2[j+1]; 127 j++; 128 l++; 129 } 130 } 131 else if(i+1 < n1) 132 { 133 res=nums1[i+1]; 134 i++; 135 l++; 136 } 137 else if(j+1 < n2) 138 { 139 res=nums2[j+1]; 140 j++; 141 l++; 142 } 143 return res; 144 } 145 } 146 };

第二種方法是神奇的二分查詢,對於題目的要求,等同於找等價序列中的第K個元素,或著K和第K加1個元素。所以對於這兩個序列,可以比較其索引為K/2-1的元素的相對大小,對於其中較小的值,其最多也只能比k-2個元素大,所以該元素包括該序列中的之前所有元素都可以排除。依照這個思路,可以在每一輪迭代中排除一部分元素,並更新K的值,不斷進行迭代。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) 
    {
        int m = nums1.size();
        int n = nums2.size();
        if(m*n == 0)
        {
            if(m)
            {
                if(m%2 == 0)
                return double(nums1[nums1.size()/2-1]+nums1[nums1.size()/2])/2;
                else
                return nums1[nums1.size()/2];
            }
            else
            {
                if(n%2 == 0)
                return double(nums2[nums2.size()/2-1]+nums2[nums2.size()/2])/2;
                else
                return nums2[nums2.size()/2];    
            }
        }
        int k = (m+n+1)/2;
        if(k == 0)
        {
            if(m)
            return nums1[0];
            else
            return nums2[0];
        }
        double res = 0;
        int m1 = 0;
        int n1 = 0;
        while(k>1)
        {
            //cout<<"good"<<endl;
            //比較當前位置大小
            if(m1+k/2-1<m && n1+k/2-1<n)
            {
                
                if(nums1[m1+k/2-1] <= nums2[n1+k/2-1])
                m1+=k/2;
                else
                n1+=k/2;
                //cout<<k<<endl;
                //cout<<k/2<<endl;
                k = k-k/2;
            }
            else if(m1+k/2-1>=m)
            {
                if(nums1[m-1] <= nums2[n1+k/2-1])
                {
                    k = k-(m-m1);
                    res+=nums2[n1+k-1];
                    if((m+n)%2 == 0)
                    {
                        res+=nums2[n1+k];
                        res/=2;
                    }
                    return res;
                }
                else
                {
                    n1+=k/2;
                    k = k-k/2;
                }
            }
            else
            {
                if(nums1[m1+k/2-1] <= nums2[n-1])
                {
                    m1+=k/2;
                    k = k-k/2;
                }
                else
                {
                    k = k-(n-n1);
                    res+=nums1[m1+k-1];
                    if((m+n)%2 == 0)
                    {
                        res+=nums1[m1+k];
                        res/=2;
                    }
                    return res;
                }
            }
            //判斷是否有序列到最後了
            if(m1>=m)
            {
                cout<<"good"<<endl;
                n1+=k-1;
                res+=nums2[n1];
                if((m+n)%2 == 0)
                {
                    res+=nums2[n1+1];
                    res/=2;
                }
                return res;
            }
            else if(n1>=n)
            {
                m1+=k-1;
                res+=nums1[m1];
                if((m+n)%2 == 0)
                {
                    res+=nums1[m1+1];
                    res/=2;
                }
                return res;
            }
        }
        if(m1>=m)
        {
            res+=nums2[n1];
            n1++;
        }
        else if(n1>=n)
        {
            res+=nums1[m1];
            m1++;
        }
        else if(nums1[m1]<=nums2[n1])
        {
            res+=nums1[m1];
            m1++;
        }
        else
        {
            res+=nums2[n1];
            n1++;
        } 
        if((m+n)%2 == 0)
        {
            if(m1>=m)
            res+=nums2[n1];
            else if(n1>=n)
            res+=nums1[m1];
            else
            {
                if(nums1[m1]<=nums2[n1])
                res+=nums1[m1];
                else
                res+=nums2[n1];
            }
            res/=2;            
        } 
        return res;     
    }
};

細節很難搞,果然和二分查詢有關的都很難搞。