题目描述:寻找两个有序数组合并后的中位数,要求算法时间复杂度为O(log(m+n))
参考官方题解。
说到中位数,两个序列合并后的中位数下标一定是m+n+1/2或中间两位数的平均数。
我们只需要不断地划分两个序列直到找到答案即可,划分序列可以用二分法,
left_part | right_part A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1] B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
用二分法寻找i,由于左右两部分数量一定相同,所以j = (m + n + 1) / 2 - i.
且划分后序列要满足右边部分要恒大于左边部分,即B[j]>=A[j-1]且B[j-1]<=A[i]。
这是满足条件的答案,还有边界情况,比如i = 0或j = n。
搜索中会遇到三种情况:
(j=0 or i = m or B[j−1]≤A[i]) 或是 (i=0 orj=n or A[i−1]≤B[j]),这意味着 i 是完美的,我们可以停止搜索。
i < m and B[j−1]>A[i] 这意味着 i 太小,我们必须增大它。
j<n and A[i−1]>B[j] 这意味着 i 太大,我们必须减小它。
代码:
class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int m = nums1.size(); int n = nums2.size(); if(m > n) {//这里为了让搜索次数最小 nums1.swap(nums2); int res = m; m = n; n = res; } int iMin = 0;int iMax = m; int mid = (m + n + 1) / 2; while(iMin <= iMax){ int i = (iMax + iMin) / 2; int j = mid - i; if(i < iMax && nums2[j - 1] > nums1[i]){ iMin = i + 1; } else if(i > iMin && nums2[j] < nums1[i - 1]){ iMax = i - 1; } else{ int ans = 0; if(i == 0){ans = nums2[j - 1];} else if(j == 0) ans = nums1[i - 1]; else ans = max(nums1[i - 1], nums2[j - 1]); if((m + n) % 2 == 1) return ans; int ans2 = 0; if(i == m) ans2 = nums2[j]; else if(j == n) ans2 = nums1[i]; else ans2 = min(nums1[i], nums2[j]); return (ans + ans2) / 2.0; } } return 0.0; } };
原文地址:https://www.cnblogs.com/txltxl22/p/11300228.html
时间: 2024-10-10 04:22:55