leetcode 4 兩個正序陣列中位數
阿新 • • 發佈:2022-01-19
普通方法,就算總的數個數,然後通過雙指標的方法訪問陣列中的元素,可以搞出來,但是時間複雜度不是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; } };
細節很難搞,果然和二分查詢有關的都很難搞。