[LeetCode] 4.两个有序数组合并后的中位数(Median of Two Sorted Arrays)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huanghaocs/article/details/81638741

1.问题描述

给定两个有序数组nums1和nums2,返回这两个数组合并的有序数组的中位数。
例:nums1 = [1,2], nums2 = [3,4,5], 返回结果是3;
nums1 = [1,2,3], nums2 = [4,5,6], 返回结果是3.5。

2.解决方法

(1)直接把这两个数组合并成一个有序数组,然后取中位数。时间复杂度O(m+n),空间复杂度O(m+n)

   public double findMedianSortedArrays(int[] nums1, int[] nums2) {
       int len1 = nums1.length;
       int len2 = nums2.length;
       int[] nums = new int[len1+len2]; // 定义数组空间,存放两个数组合并结果
       int index1 = 0, index2 = 0, i=0;
       // 先扫描两个数组大小重叠的部分
       while(index1 < len1 && index2 < len2){
           if(nums1[index1] < nums2[index2]){
               nums[i++] = nums1[index1];
               index1++;
           }else{
               nums[i++] = nums2[index2];
               index2++;
           }
       }
       // nums2扫描完毕,剩余nums1元素都大于nums2元素
       while(index1 < len1){
           nums[i++] = nums1[index1];
           index1++;
       }
       // nums1扫描完毕,剩余nums2元素都大于nums1元素
       while(index2 < len2){
           nums[i++] = nums2[index2];
           index2++;
       }
       double med = 0;
       int len = nums.length;
       // 总共为偶数个,中间值是数组中间两个元素平均
       if(len % 2 == 0){
           med = (nums[len/2 - 1] + nums[len/2])*1.0 / 2;
       }else{ // 总共为奇数个,中间值是就是数组中间的元素
           med = nums[len/2];
       }
       return med;
   }

(2)考虑合并后求的是中位数,把数组分成两块,只要找到中间那个数就可以。

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int m = nums1.length;
    int n = nums2.length;

    // 先判断是否有一个数组为空
    double med = 0;
    int k = (m+n) / 2;
    if(m == 0){
        if(n % 2 == 0)
            med = (nums2[n/2-1] + nums2[n/2])*0.5;
        else
            med = nums2[n/2];
        return med;
    }
    if(n == 0){
        if(m % 2 == 0)
            med = (nums1[m/2-1] + nums1[m/2])*0.5;
        else
            med = nums1[m/2];
        return med;
    }

    // 不为空,保证len(nums1) < len(nums1),如果不是交换位置
    if(m > n){
        return findMedianSortedArrays(nums2, nums1);
    }
    int iMin = 0, iMax = m;
    while(iMin <= iMax){
        int i = (iMin + iMax) / 2;
        int j = (m + n + 1) /2 - i;
        if(j != 0 && i != m && nums2[j-1] > nums1[i]) 
            iMin = i + 1;
        else if(i != 0 && j != n && nums1[i-1] > nums2[j])
            iMax = i - 1;
        else{
            int maxLeft = 0;
            if(i == 0)
                maxLeft = nums2[j-1];
            else if(j == 0)
                maxLeft = nums1[i-1];
            else
                maxLeft = Math.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 = Math.min(nums2[j], nums1[i]);

            return (maxLeft + minRight) / 2.0; // 偶数需要取半

        }

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/huanghaocs/article/details/81638741
今日推荐