力扣4. 寻找两个正序数组的中位数
一道困难题,常规思路不难,但是真的难写,边界要仔细思考。
下面是我第一轮的思路,虽然非常常规,但是时间复杂度并不高,注意要把奇数偶数分开写,一个是降低了时间复杂度,另一个是好写。。。不然会出现一堆判断或者三目表达式。
1 class Solution { 2 public: 3 double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { 4 int n1 = nums1.size(), n2 = nums2.size(); 5 int n = n1 + n2; 6 int num = INT_MIN; 7 int i = 0, i1 = 0, i2 = 0; 8 int hn = n / 2; 9 if (n & 1) { 10 for (; ; ++i) { 11 if (i1 < n1 && i2 < n2) { 12 if (i == hn) return 1.0 * min(nums1[i1], nums2[i2]); 13 if (nums1[i1] > nums2[i2]) i2++; else i1++; 14 } else if (i1 >= n1) { 15 return nums2[hn - n1]; 16 } else if (i2 >= n2) { 17 return nums1[hn - n2]; 18 } 19 } 20 } else { 21 for (; ; ++i) { 22 if (i1 < n1 && i2 < n2) { 23 if (i == hn - 1) num = min(nums1[i1], nums2[i2]); 24 else if (i == hn) return (num + min(nums1[i1], nums2[i2])) / 2.0; 25 26 if (nums1[i1] > nums2[i2]) i2++; else i1++; 27 } else if (i1 >= n1) { 28 return INT_MIN == num ? (nums2[hn - n1 - 1] + nums2[hn - n1]) / 2.0 : (num + nums2[i2]) / 2.0; 29 } else if (i2 >= n2) { 30 return INT_MIN == num ? (nums1[hn - n2 - 1] + nums1[hn - n2]) / 2.0 : (num + nums1[i1]) / 2.0; 31 } 32 } 33 } 34 return 0; 35 } 36 };
下面这个做法是参考官方题解,写了一遍,满足题目要求的O(log (m+n)时间复杂度,不过实际试了一下,大量测试用例中,元素较少的情况下,时间复杂度反倒变高了。
这种做法最终要的几个点如下
① 要按照第k大的数来找,不要一门心思的找中数,容易陷入奇数偶数的大量判断中。
② 代码量不大,想理解并且快速手搓一遍不容易,理解思路+边界判断。
1 class Solution { 2 public: 3 int findk(vector<int>& nums1, vector<int>& nums2, int k) 4 { 5 int n1 = nums1.size(), n2 = nums2.size(); 6 int i1 = 0, i2 = 0; 7 for (;;) { 8 if (i1 == n1) return nums2[i2 + k - 1]; 9 if (i2 == n2) return nums1[i1 + k - 1]; 10 if (1 == k) return min(nums1[i1], nums2[i2]); 11 int hk = k / 2; 12 int ti1 = min(i1 + hk, n1) - 1; 13 int ti2 = min(i2 + hk, n2) - 1; 14 // printf("In, k = %d, hk = %d, i1 = %d, i2 = %d, ti1 = %d, ti2 = %d, [ %s ]\n", 15 // k, hk, i1, i2, ti1, ti2, nums1[ti1] > nums2[ti2] ? "if" : "else"); 16 if (nums1[ti1] > nums2[ti2]) { 17 k -= min(hk, n2 - i2); 18 i2 = ti2 + 1; 19 } else { 20 k -= min(hk, n1 - i1); 21 i1 = ti1 + 1; 22 } 23 // printf("Out, k = %d, i1 = %d, i2 = %d\n", k, i1, i2); 24 } 25 } 26 27 double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { 28 int n1 = nums1.size(), n2 = nums2.size(); 29 int n = n1 + n2; 30 if (n & 1) 31 return findk(nums1, nums2, (n + 1) / 2); 32 else 33 return (findk(nums1, nums2, n / 2) + findk(nums1, nums2, n / 2 + 1)) / 2.0; 34 } 35 };