从零开始刷Leetcode day03 寻找两个正序数组的中位数(Median of Two Sorted Arrays)

寻找两个正序数组的中位数(Median of Two Sorted Arrays)-java解法

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
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)).
You may assume nums1 and nums2 cannot be both empty.
示例1:

nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0

示例2:

nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5

暴力解法:

先将两个数组合并,两个有序数组的合并也是归并排序中的一部分。然后根据奇数,还是偶数,返回中位数。
代码:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n1 = nums1.length;
        int n2 = nums2.length;
        int[] merge = new int[n1+n2];
        int p= 0;
        int q = 0;
        int count = 0;
        while(p<n1 && q<n2){
            if(nums1[p]<nums2[q]){
                merge[count++] = nums1[p++];
            }else{
                merge[count++] = nums2[q++];
            }
        }while(p<n1){
            merge[count++] = nums1[p++];
        }while(q<n2){
            merge[count++] = nums2[q++];
        }
        int isOdd = (n1+n2)%2;
        if(isOdd == 1){
            int mid = (n1+n2-1)/2;
            return merge[mid];
        }else{
            int mid = (n1+n2)/2-1;
            return (merge[mid]+merge[mid+1])/2.0;
            
        }
    }
}

注意: 题目要求时间复杂度为O(log(m+n)),如果对时间复杂度的要求有 log,通常都需要用到二分查找,这道题也可以通过二分查找实现。

二分解法:

  • 假设我们要找第 k 小数,我们可以每次循环排除掉 k/2 个数。

  • 假设两个有序数组分别是A和B。要找到第 k个元素,我们可以比较 A[k/2−1] 和B[k/2−1]。由于A[k/2−1] 和B[k/2−1] 的前面分别有A[0…k/2−2] 和B[0…k/2−2],即k/2−1 个元素,对于A[k/2−1] 和B[k/2−1] 中的较小值,最多只会有(k/2−1)+(k/2−1)≤k/2−2 个元素比它小,那么它就不能是第 k小的数了。

  • 因此我们可以归纳出三种情况:

  • 如果A[k/2−1]<B[k/2−1],则比 \text{A}[k/2-1]A[k/2−1] 小的数最多只有A 的前 k/2−1 个数和B 的前 k/2−1 个数,即比A[k/2−1] 小的数最多只有k−2 个,因此A[k/2−1] 不可能是第 k 个数,A[0] 到A[k/2−1] 也都不可能是第 k 个数,可以全部排除。

  • 如果]A[k/2−1]>B[k/2−1],则可以排除B[0] 到B[k/2−1]。

  • 如果A[k/2−1]=B[k/2−1],则可以归入第一种情况处理。
    代码:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n1 = nums1.length;
        int n2 = nums2.length;
        //无论总长度为技术还是偶数均可处理。
        return (getKth(nums1,0,n1-1,nums2,0,n2-1,(n1+n2+1)/2)+
               getKth(nums1,0,n1-1,nums2,0,n2-1,(n1+n2+2)/2))*0.5;
    }
	private  double getKth(int[] nums1,int start1,int end1,int[] nums2,int start2,int end2,int k){
        int len1 = end1-start1+1;
        int len2 = end2-start2+1;
         if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
         //统一为len1<len2的情况,方便后面处理。
        if(len1 == 0){
            return nums2[start2+k-1];
        }//其中一个数组为空时,继续从另一个数组中取第n个数
        if(k == 1){
            return Math.min(nums1[start1],nums2[start2]);
        }//取第一个数,则取两个数组开始位置的更小的那个
        
        else{
            int i = start1 + Math.min(len1,k/2)-1;
            int j = start2 + Math.min(len2,k/2)-1;
            //每次去掉k-2个数,如果超出其中的某个数组的长度,则去掉数组中的全部数
            if(nums1[i]>nums2[j]){
                return getKth(nums1,start1,end1,nums2,j+1,end2,k-(j-start2+1));
            }else{
                return getKth(nums1,i+1,end1,nums2,start2,end2,k-(i-start1+1));
            }//迭代直至k==1
            
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值