leetcode4. 寻找两个正序数组的中位数-java(困难)

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

原题链接

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

算法的时间复杂度应该为 O(log (m+n)) 。

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

提示:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106

题解

常规思路是在创建一个数组 然后排序 这样的作法是O(nlog n)的时间复杂度 但是这题的要求复杂度在log(m+n)中,于是我们可以转换思想
将题目所求可以变成一个寻找第K个数 因为题目给出的是正序数组
找中位数k=(n + m) / 2,等价于找第k小的元素,k = (n + m) / 2
1、当一共有偶数个数时,找到第total / 2小left和第total / 2 + 1小right,结果是(left + right / 2.0)
2、当一共有奇数个数时,找到第total / 2 + 1小,即为结果 在这里插入图片描述
首先默认第一个数组比第二个数组短 如果不是 那么调换顺序
nums1从i 开始 nums2从j开始
[i,si-1]表示nums1里面前k/2个元素
[j,sj]表示的nums2里面前k-k/2个元素
当nums1[si - 1] > nums2[sj - 1]时,则表示第k小一定在[i,n]与[sj,m]中
也就是舍弃了nums2的前一部分
当nums1[si - 1] <= nums2[sj - 1]时,则表示第k小一定在[si,n]与[j,m]中
就是舍弃了nums1的前一部分
考虑边界的情况:
第一个数组用完
数组就两个元素

时间复杂度分析:k=(m+n)/2k=(m+n)/2,且每次递归 kk 的规模都减少一半,因此时间复杂度是 O(log(m+n))O(log(m+n)).

代码案例:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
         int total = nums1.length + nums2.length;
         if(total%2 == 0){
             int left = f(nums1,0,nums2,0,total/2);
             int right = f(nums1,0,nums2,0,total/2 +1);
             return (left+right)/2.0 ;//除以2的话会取整
         }else return f(nums1,0,nums2,0,total/2+1);
    }
    static int f(int[] nums1 ,int i , int[] nums2,int j,int k){
        //默认第一个数组的长度小
        if(nums1.length -i> nums2.length-j) return f(  nums2 , j,   nums1  ,i , k);
       
        //如果第一个数组用完
        if(nums1.length == i ) return nums2[j+k-1];
        if(k== 1 ) return Math.min(nums1[i],nums2[j]);
        //只有一个长度的时候
	//两个有效长度
        int si = Math.min(nums1.length,i + k /2) ;
        //si如果不取最小的话  就会出现出界的问题  因为si可能为0 本身就短
        int sj = j + k - k /2 ;
        if(nums1[si-1] < nums2 [sj-1]) return f(nums1,si,nums2,j,k - (si - i));
       else return f(nums1,i,nums2,sj,k -(sj-j));
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依嘫_吃代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值