Loading

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对应数量的位置。

  1. len(left_part)=len(right_part)
  2. 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; } };

 

posted @ 2018-09-28 10:34  老鼠阿尔吉侬  阅读(135)  评论(0)    收藏  举报