leetcode:寻找两个正序数组的中位数

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
方法一:暴力解法(不符合时间复杂度要求)
时间复杂度O(m+ n) 空间复杂度O(m + n)

package Algorithm;

public class findMedianSortedArrays1 {
    public int[] num1;
    public int[] num2;
    public double findMedianSortedArrays(int[] num1, int[] num2){
        this.num1 = num1;
        this.num2 = num2;
        //这里n1和n2保存的是两个数组的元素个数
        int n1 = num1.length - 1;
        int n2 = num2.length - 1;
        int[] add = new int[n1 + n2 + 2];

        if (n1 == 0){
            if (n2 % 2 == 0){
                return (num2[n2/2] + num2[n2/2 + 1]) / 2.0;
            }
            else return num2[n2/2];
        }

        if (n2 == 0){
            if (n1 % 2 == 0){
                return (num2[n1/2] + num2[n1/2 + 1]) / 2.0;
            }
            else return num2[n1/2];
        }

        int count = 0;
        int i = 0;
        int j = 0;
        while (i != n1 && j != n2){
            if (num1[i] < num2[j]){
                add[count++] = num1[i++];
            }
            else add[count++] = num2[j++];
        }

        while (i <= n1){
            add[count++] = num1[i++];
        }

        while (j <= n2){
            add[count++] = num2[j++];
        }

        if (add.length % 2 == 0){
            return (add[(n1 + n2)/2] + add[(n1 + n2)/2 + 1]) / 2.0;
        }

        else return add[(n1 + n2)/2];
    }

}

测试代码:

public class findMedianSortedArrays1Test {
    public static void main(String[] args) {
        int[] num1 = {1, 3, 4 ,9};
        int[] num2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        findMedianSortedArrays1 fms = new findMedianSortedArrays1();
        System.out.println(fms.findMedianSortedArrays(num1, num2));
        int[] num3 = {1, 2};
        int[] num4 = {3, 4};
        findMedianSortedArrays1 fms1 = new findMedianSortedArrays1();
        System.out.println(fms1.findMedianSortedArrays(num3, num4));
    }
}

方法二:
假设我们要找第 k 小数,我们可以每次循环排除掉 k/2 个数。
从上边可以看到,无论是找第奇数个还是第偶数个数字,对我们的算法并没有影响,而且在算法进行中,k 的值都有可能从奇数变为偶数,最终都会变为 1 或者由于一个数组空了,直接返回结果。
所以我们采用递归的思路,为了防止数组长度小于 k/2,所以每次比较 min(k/2,len(数组) 对应的数字,把小的那个对应的数组的数字排除,将两个新数组进入递归,并且 k 要减去排除的数字的个数。递归出口就是当 k=1 或者其中一个数字长度是 0 了。

链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/

package Algorithm;

import javax.swing.*;

public class findMedianSortedArrays2 {
    int[] num1;
    int[] num2;
    public double findMedianSortedArrays2(int[] num1, int[] num2){
        this.num1 = num1;
        this.num2 = num2;
        int n1 = num1.length;
        int n2 = num2.length;
        //若为偶数我们则需要求左中位数和右中位数取平均
        int left = (n1 + n2 + 1) / 2;
        int right = (n1 + n2 + 2) / 2;
        //这样若总长度为偶数则计算出left和right,若为奇数则计算两遍取平均
        return (getKth(num1, 0, n1 - 1, num2, 0, n2 - 1, left) +
                getKth(num1, 0, n1 - 1, num2, 0, n2 - 1, right)) / 2.0;
    }

    private int getKth(int[] num1, int from1, int to1, int[] num2, int from2, int to2, int k){
        int len1 = to1 - from1 + 1;
        int len2 = to2 - from2 + 1;
        //为了确保我们如果有空数组,那么空数组一定为num1
        if (len1 > len2){
            return getKth(num2, from2, to2, num1, from1, to1, k);
        }
        if (len1 == 0){
            //如果数组1为空,那么只需要求得数组2中第k大的数字
            return num2[from2 + k - 1];
        }

        if (k == 1){
            //如果最后两个数组都只保存一个数字时,比较他俩的大小,选择更小的那个
            return Math.min(num1[from1], num2[from2]);
        }

        //判断当前数组长度是否小于k,如果小于,则取当前数组最后一个元素
        int i = from1 + Math.min(len1, k / 2) - 1;
        int j = from2 + Math.min(len2, k / 2) - 1;

        if (num1[i] < num2[j]){
            return getKth(num1, i + 1, to1, num2, from2, to2, k - (i - from1 + 1));
        }
        else return getKth(num1, from1, to1, num2, j + 1, to2, k - (j - from2 + 1));
    }
}

测试代码:

package Test;

import Algorithm.findMedianSortedArrays1;
import Algorithm.findMedianSortedArrays2;

public class findMedianSortedArrays2Test {
    public static void main(String[] args) {
        int[] num1 = {1, 3, 4 ,9};
        int[] num2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        findMedianSortedArrays2 fms = new findMedianSortedArrays2();
        System.out.println(fms.findMedianSortedArrays2(num1, num2));
        int[] num3 = {1, 2};
        int[] num4 = {3, 4};
        findMedianSortedArrays2 fms2 = new findMedianSortedArrays2();
        System.out.println(fms2.findMedianSortedArrays2(num3, num4));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值