LeetCode 03 Median of Two Sorted Arrays

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

题目大意:
给你两个长度分别为m和n的有序数列,将他们排序成为一个数组,并求中间元素的平均值.时间复杂度为O(log(m+n))


看见这个题第一反应就是归并排序,这个题目给的就是有序数列,所以更简单,只需要合并数组即可.题目要求是计算中间元素的平均值,如果合并完成后数列长度为奇数,那么中间元素只有一个,如果为偶数,中间元素有两个,那我们在合并时就不需要把数组都遍历,只找到前一半+1的数据即可.

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int i = 0, j = 0, k = 0;
        int len1 = nums1.length;
        int len2 = nums2.length;
        int res[] = new int[len1+len2];
        double med;
        int mid = (len1 + len2) / 2;
        //合并数组
        //判断两个数组是否遍历完,以及结果数组的长度是否为一半
        while(i < len1 && j < len2 && k < mid+1){
            if(nums1[i] < nums2[j]){
                res[k] = nums1[i];
                k++;
                i++;
            }else{
                res[k] = nums2[j];
                k++;
                j++;
            }
        }
        //如果nums2遍历完但是还没找到中间的元素,继续遍历nums1
        while(k < mid + 1 && i < len1){
            res[k] = nums1[i];
            i++;
            k++;
        }
        //如果nums1遍历完但是还没找到中间的元素,继续遍历nums2
        while(k < mid + 1 && j < len2){
            res[k] = nums2[j];
            j++;
            k++;
        }
        //判断中间元素有一个还是两个
        if((len1 + len2) % 2 == 0){
            med = (double)(res[mid] + res[mid-1])/2;
        }else{
            med = (double)res[mid];
        }
        return med;  
        }
}

还有一种二分的方法,来自http://blog.csdn.net/hk2291976/article/details/51107778,里面分析很详细,我就不贴过来了.
只是在下面的代码中,和分析中有所不同的是把所有的数组长度都*2,那么都变成了偶数数组
代码:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size();
        int m = nums2.size();
        if(n > m)   //保证数组1一定最短
            return findMedianSortedArrays(nums2,nums1);
        int L1,L2,R1,R2,c1,c2,lo = 0, hi = 2*n;  //我们目前是虚拟加了'#'所以数组1是2*n长度
        while(lo <= hi)   //二分
        {
            c1 = (lo+hi)/2;  //c1是二分的结果
            c2 = m+n- c1; //寻找的是第m+n个和第m+n+1个元素,在数组中的下标为m+n-1和m+n
            //判断边界情况并对它们赋值
            L1 = (c1 == 0)?INT_MIN:nums1[(c1-1)/2];   //赋值时候就还原数组的位置
            R1 = (c1 == 2*n)?INT_MAX:nums1[c1/2];
            L2 = (c2 == 0)?INT_MIN:nums2[(c2-1)/2];
            R2 = (c2 == 2*m)?INT_MAX:nums2[c2/2];

            if(L1 > R2)
                hi = c1-1;
            else if(L2 > R1)
                lo = c1+1;
            else
                break;
        }
        return (max(L1,L2)+ min(R1,R2))/2.0;
    }
};

猜你喜欢

转载自blog.csdn.net/zxm490484080/article/details/79593337