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

题目描述:
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。

要求:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?

来源:力扣(LeetCode)
链接:题目链接

解答方法:由于题目要求在log时间内找出中位数,显然先合并为一个数组然后找中位数,或者使用双指针进行两个数组的扫描,查找中位数的时间均是不符合要求的。一般要求在log时间内完成多半要联系二分法。那么对于该题怎么使用二分法呢?
采用前面的方式我们一次只能排除一个元素,如果要达到二分的时间要求,我们就需要一次排除多个元素。我们可以这样判断。设两个数组分别为nums1[ ], nums2[ ]. 我们要找的假设是第k个元素,那么我们分别在两个数组中寻找k/2个元素,当num1[start1 + k/2 - 1] <= num2[start2 + k/2 - 1]的时候,我们扔掉num1数组当前位置之前的元素,此处start1表示当前还未进行判断的第一个元素(意味着该元素在需要在本次进行判断,所以最后要-1). 否则我们扔掉num2中应该排除的元素。
由于数组元素的长度可能是奇数也可能是偶数,所以寻找中位数还有一个技巧是,我们定义 int k1 = (num1.length + num2.length + 1)/2;int k2 = (num1.length + num2.length + 2)/2; 我们寻找这两个位置的元素,然后加起来除以2.0便是我们需要寻找的中位数。因为当元素长度是奇数的时候k1和k2是相等的。
具体实现代码如下:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if((nums1 == null || nums1.length == 0) && (nums2 == null || nums2.length == 0)){
            return 0.0;
        }
        int m = nums1.length;
        int n = nums2.length;
        int k1 = (m + n + 1)/2;
        int k2 = (m + n + 2)/2;
        if(k1 == k2){
            return getKthNumber(nums1, 0, m - 1, nums2, 0, n - 1, k1);
        }
        return (getKthNumber(nums1, 0, m - 1, nums2, 0, n - 1, k1) + getKthNumber(nums1, 0, m - 1, nums2, 0, n - 1, k2))/2.0;
    }
    public double getKthNumber(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k){
        //下标为0代表第一个元素那么为什么需要加1呢?是因为后面判断的需要(当排除一些数的时候,起始位置加1了,如果判断的位置刚好是最末尾的元素,那么start会大于end)
        int len1 = end1 - start1 + 1;
        int len2 = end2 - start2 + 1;
        if(len1 > len2){//我们始终保持len2>len1,因为这样如果数组中的元素不够第k个的时候,一定是len1不够了
            return getKthNumber(nums2, start2, end2, nums1, start1, end1, k);
        }
        if(len1 == 0) {//说明nums1数组整个都被排除掉了
            return nums2[start2 + k - 1];
        }
        if(k == 1){//递归的出口条件
            return Math.min(nums1[start1], nums2[start2]);
        }
        //计算当前需要判断的数组下标位置,这样计算下标位置的目的是当不够k/2个数的时候会自动指向数组的末尾
        int i = start1 + Math.min(len1, k/2) - 1;
        int j = start2 + Math.min(len2, k/2) - 1;
        if(nums1[i] < nums2[j]){//说明需要扔掉nums1数组中的前i个元素
            return getKthNumber(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
        }else{
            return getKthNumber(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
        }
    }
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值