leetcode 4. 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

解析:
这道题看着貌似简单,实际上没有那么简单~
首先上我自己写的超级笨拙的代码(JAVA,当然还可以优化~):

 public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int len=nums1.length+nums2.length;
            if(len==0){
                return 0;
            }
            if(nums1.length<nums2.length){          
                return findMedianSortedArrays(nums2,nums1);
            }

            boolean even=false;
            int middle;

            if (len%2==0){
                even=true;
                middle=len/2;
            }else{
                middle=(len+1)/2;
            }

            if(nums2.length==0){
                if(even)
                    return ((double)nums1[middle-1]+(double)nums1[middle])/2;
                else
                    return (double)nums1[middle-1];
            }
            int temp=0;
            int middleValue=0;
            int i=0;
            int j=0;
            for (;i<nums1.length+1;){
                if(j==nums2.length&&i==nums1.length){
                    break;
                }
                if(j==nums2.length){
                    temp++;
                    i++;
                    if(temp==middle&&!even)
                        return (double)nums1[i-1];
                    if(temp==middle&&even)
                        middleValue=nums1[i-1];
                    if(temp==(middle+1)&&even)
                        return ((double)middleValue+(double)nums1[i-1])/2;
                    continue;
                }
                for(;j<nums2.length;){    
                    if(nums1.length==i){
                        temp++;
                        j++;
                        if(temp==middle&&!even)
                            return (double)nums2[j-1];
                        if(temp==middle&&even)
                            middleValue=nums2[j-1];
                        if(temp==middle+1&&even)
                            return ((double)middleValue+(double)nums2[j-1])/2;
                        continue;
                    }
                    if(nums1[i]<nums2[j]){
                        temp++;
                        i++;
                        if(temp==middle&&!even)
                            return (double)nums1[i-1];
                        if(temp==middle&&even)
                            middleValue=nums1[i-1];
                        if(temp==(middle+1)&&even)
                            return ((double)middleValue+(double)nums1[i-1])/2;
                        break;
                    }else if (nums1[i]>nums2[j]){
                        temp++;
                        j++;
                        if(temp==middle&&!even)
                            return (double)nums2[j-1];
                        if(temp==middle&&even)
                            middleValue=nums2[j-1];
                        if(temp==(middle+1)&&even)
                            return ((double)middleValue+(double)nums2[j-1])/2;
                    }else{
                        i++;
                        j++;
                        temp=temp+2;
                        if((temp==middle||temp-1==middle)&&!even)
                            return (double)nums2[i-1];
                        if((temp==middle||temp-1==middle)&&even)
                            middleValue=nums1[i-1];
                        if((temp==(middle+1)||temp-1==middle+1)&&even)
                            return ((double)middleValue+(double)nums2[i-1])/2;
                        break;
                    }
                }               
            }
            return 0;
     }

以上代码实际上就是一个排序~,因为给的数组是有序的,因此当它排到中位数的时候就返回了,此时若m+n为偶数时,它执行m+n/2次,奇数同理。所以时间复杂度为O(n)。不符合要求~~但是leetcode木有提示,仔细看题目,时间复杂度要求O(log(m+n)).

然后,去网上搜了一下牛人的解答:leetcode之 median of two sorted arrays

里面证明也写的很详细,好汗颜~,具体用go语言实现了一下,因为java代码有点不方便。leetcode accept了

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
        m:= len(nums1)
        n:=len(nums2)
        total := m+n;  
        if total%2==1 {
              return findKth(nums1, m, nums2, n, total / 2 + 1)
        }  else {
            return (findKth(nums1, m, nums2, n, total / 2)+ findKth(nums1, m, nums2, n, total / 2 + 1)) / 2
        } 

}

func findKth(nums1 []int,size1 int, nums2 []int,size2 int ,k int) float64{
        if size1>size2{
            return findKth(nums2,size2,nums1,size1,k)
        }

        if size1==0{
            return float64(nums2[k-1])
        }

        if k==1{
            if nums1[0]>nums2[0]{
                return float64(nums2[0])
            }
            return float64(nums1[0])
        }

        pa:=k/2
        if pa>size1{
            pa=size1
        }
        pb:=k-pa

        if nums1[pa-1]>nums2[pb-1]{
            return findKth(nums1,size1,nums2[pb:size2],size2-pb,k-pb)
        }else if nums1[pa-1]<nums2[pb-1]{
            return findKth(nums1[pa:size1],size1-pa,nums2,size2,k-pa)
        }else{
            return float64(nums1[pa-1])
        }

}

一看到时间复杂度为log**那么第一应该想到的就是二分搜索。此算法,算是二分删除。
一开始觉得此算法会漏掉一些情况,比如1,3,4,5和2,3,4,5,6这个情况此时k/2是2(舍掉小数位后面的),那么此时3=3,而3并不是中位数。实际上两个数组比较的索引是这样算的:

pa:=k/2 if pa>size1{ pa=size1 } pb:=k-pa

这样保证了相等时就是中位数,因为pa+pb=k。当然前提数组是升序排列。

点赞