leetcode#4Median of Two Sorted Arrays
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。
示例 1:
nums1 = [1, 3]
nums2 = [2]中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]中位数是 (2 + 3)/2 = 2.5
思路:
这道题官方解法比较好。
对num1进行二分查找,再找num2对应数量的位置。
- len(left_part)=len(right_part)
- max(left_part) <left(right_part)这意味着两种失败情况,m[i]>n[i+1] || n[i]>m[i+1]
比如1,2,4,5,9和0,3,6,7,8。第一次查找,12/459和036/78,显然2,6|4,7不可以,1245/9+++0/3678,05/39不可以。
最后划到了124/59和03/678,显然3,4|5,6可以组成一个有序的序列。
现在问题就是如果出现12|459和036|78怎么修改边界的问题了。4<6说明强行以4作为中位数会使得更大的数出现在左侧,我们只有向右移动"|",这样,4可能出现在左边,6则出现在右边。
class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { if (nums1.size() > nums2.size()) swap(nums1,nums2); int m=nums1.size(),n=nums2.size(); int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;//这里为什么要+1呢?不加也可以,但后面的判断要修改了。
//比如[2][1,3] 第一次划分1|23就返回了。虽然它满足条件1和2,但1显然不是答案。我们需要保证左边始终和右边相等,或者左边比右边多一个。这样当m+n为奇数时,左边的最大值,刚好就是中位数。
while (iMin <= iMax)//我们还要小心处理边界,0-iMax都是可能作为答案的值,因为索引i即“|”的位置,不包括当前元素,而iMax是个无效索引。
{ int i = (iMin + iMax) / 2; int j = halfLen - i;//这个条件使得我们必须保证m<n if (i < iMax && nums2[j-1] > nums1[i]) iMin = i + 1; // i is too smallelse if (i > iMin && nums1[i-1] > nums2[j]) iMax = i - 1; // i is too bigelse
{ // i is perfect int maxLeft = 0; if (i == 0) { maxLeft = nums2[j-1]; } else if (j == 0) { maxLeft = nums1[i-1]; } else { maxLeft = max(nums1[i-1], nums2[j-1]); } if ( (m + n) % 2 == 1 ) { return maxLeft; } int minRight = 0; if (i == m) { minRight = nums2[j]; } else if (j == n) { minRight = nums1[i]; } else { minRight = min(nums2[j], nums1[i]); } return (maxLeft + minRight) / 2.0; } } return 0.0; } };

浙公网安备 33010602011771号