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

题意:

两个已排好序的数组,找出中位数,长度为奇数则是中间那个数,偶数则是中间两个数的平均值,复杂度要求O(log (m+n))。

思路:

可以转换为求在两个已排好序的数组中找第k个数。

设数列A元素个数为n,数列B元素个数为m,各自升序排序,求第k小元素

取A[k / 2] B[k / 2] 比较,如果 A[k / 2] > B[k / 2] 那么,所求的元素必然不在B的前k / 2个元素中,因为a中比B[k / 2]小的少于k/2个。
于是可以将A或B数列的前k/2元素删去,求剩下两个数列的k-k/2小元素,于是得到了数据规模变小的同类问题,递归解决。
如果 k / 2 大于某数列个数,所求元素必然不在另一数列的前k / 2个元素中,同上操作就好。

代码:

public class Solution {
    public int findkth(int[] nums1,int []nums2,int pos1,int pos2,int k){
//        if(pos1==0&&pos2==0) System.out.println("---begin---");
        System.out.println("pos1:"+pos1+" pos2:"+pos2+" k:"+k);
        if(pos1>=nums1.length) return nums2[pos2+k-1];
        if(pos2>=nums2.length) return nums1[pos1+k-1];
        if(k==1){
            if(nums1[pos1]<=nums2[pos2]) return nums1[pos1];
            return nums2[pos2];
        }
        int index1=pos1+(k>>1)-1,index2=pos2+(k>>1)-1;
//        System.out.println("index1:"+index1+" index2:"+index2);
        int val1=((index1>=nums1.length)?Integer.MAX_VALUE:nums1[index1]);
        int val2=(index2>=nums2.length)?Integer.MAX_VALUE:nums2[index2];
        if(val1>=val2){
            return findkth(nums1,nums2,pos1,pos2+(k>>1),k-(k>>1));
        }
        else{
            return findkth(nums1,nums2,pos1+(k>>1),pos2,k-(k>>1));
        }
    }
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if(nums1.length+nums2.length==0) return 0;
        int k=(nums1.length+nums2.length+1)>>1;
        if(((nums1.length+nums2.length)&1)==1){
            return findkth(nums1,nums2,0,0,k);
        }
        return (findkth(nums1,nums2,0,0,k)+findkth(nums1,nums2,0,0,k+1))/2.0;
    }
}

另外,如果 k / 2 大于某数列个数,设该数列还有num未比较,可以比较该数列最后一个与另外一个数列的第k-num个数,同样的道理谁大删除另外一边。这里要注意的是,第二个数组可能没有足够的个数,需要每次保证先分配小的。如数据

2 3 4 5 6
1
找第4个数,如果第一个数组分配2个,第2个数组则没有2个可以分配

这种方法会稍快一些,这题时间卡的严格,k/2可以写成k>>1来优化

代码:

public class Solution {
    public int findkth_pre(int[] nums1,int []nums2,int pos1,int pos2,int k){
        if(pos1==nums1.length) return nums2[pos2+k-1];
        if(pos2==nums2.length) return nums1[pos1+k-1];
        if(k==1){
            if(nums1[pos1]<=nums2[pos2]) return nums1[pos1];
            return nums2[pos2];
        }
        int index1,index2;
        //保证小的分配不超过长度 谁小先分配谁
        if(nums1.length-pos1<nums2.length-pos2){
            index1=pos1+(k>>1)-1;
            if(index1>=nums1.length) index1=nums1.length-1;
            index2=pos2+k-(index1-pos1+1)-1;
        }
        else{
            index2=pos2+(k>>1)-1;
            if(index2>=nums2.length) index2=nums2.length-1;
            index1=pos1+k-(index2-pos2+1)-1;
        }
        if(nums1[index1]>nums2[index2]){
            return findkth_pre(nums1,nums2,pos1,index2+1,k-(index2-pos2+1));
        }
        else{
            return findkth_pre(nums1,nums2,index1+1,pos2,k-(index1-pos1+1));
        }
    }
    
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if(nums1.length+nums2.length==0) return 0;
        int k=(nums1.length+nums2.length+1)>>1;
        if(((nums1.length+nums2.length)&1)==1){
            return findkth_pre(nums1,nums2,0,0,k);
        }
        return (findkth_pre(nums1,nums2,0,0,k)+findkth_pre(nums1,nums2,0,0,k+1))/2.0;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值