leetcode-4寻找两个有序数组的中位数

题目描述

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

题目示例

示例1

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

示例2

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

题目分析

首先要求log级别的时间复杂度,那么肯定需要归并、二分这一类的操作。
我们假定第一个数组的长度小于第二个数组的长度,那么根据中位数的性质:将一组数据分为两组等长的数据,那么我们可以使得i为A数组分割点,j为B数组分割点,其中
A [ 0 , i − 1 ] . l e n + B [ 0 , j − 1 ] . l e n = A [ i , A . l e n ] . l e n + B [ j , B . l e n ] . l e n = ( A . l e n + B . l e n ) / 2 A[0,i-1].len+B[0,j-1].len = A[i,A.len].len+B[j,B.len].len\\=(A.len+B.len)/2 A[0,i1].len+B[0,j1].len=A[i,A.len].len+B[j,B.len].len=(A.len+B.len)/2
那么我们就可以通过这个条件来寻找i指针的位置,那么我们该如何调整i的位置呢?
fen
根据上图,我们需要
B [ j − 1 ] < = A [ i ] & & A [ i − 1 ] < = B [ j ] B[j-1]<=A[i] \& \& A[i-1]<=B[j] B[j1]<=A[i]&&A[i1]<=B[j]
所以根据上式调整就好了,详情见代码分析

java代码

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        if(m>n){
            int[] temp = nums1;
            nums1 = nums2;
            nums2 = temp;
            System.out.println(nums1.length);
            System.out.println(nums2.length);
            int tep = m;
            m = n;
            n = tep;
        }
        // 处理一个数组为空的情况
        if(m == 0){
            double ans = 0.0;
            if(n%2 == 0){
                ans = (nums2[n/2]+nums2[n/2-1])/2.0;
            }else{
                ans = (nums2[n/2]);
            }
            return ans;
        }
        int iMin = 0,iMax = m-1,midLen = (m+n+1)/2;//    /4+5,5+5/
        while(iMin<=iMax){
            System.out.println("iMin = " + iMin);
            System.out.println("iMax = " + iMax);
            int i = (iMax+iMin)/2;
            // m<n,保证j>=0
            int j = midLen-i;
            // 进行指针的调整
            System.out.println("i = " + i);
            System.out.println("j = " + j);
            if(i<iMax && nums2[j-1]>nums1[i]){
                iMin = i + 1; // i偏小
            }else if(i>iMin && nums1[i-1]>nums2[j]){
                iMax = i - 1;// i 偏大
            }else{
                // i 合适
                // 这时需要讨论特殊情况
                int leftMax = 0;
                if(i==0){
                    leftMax = nums2[j-1];
                }else if(j==0){
                    leftMax = nums1[i-1];
                }else{
                    leftMax = Math.max(nums1[i-1],nums2[j-1]);
                }

                int rightMin = 0;
                if(i==m){
                    rightMin = nums2[j];
                }else if(j==n){
                    rightMin = nums1[i];
                }else{
                    rightMin = Math.min(nums1[i],nums2[j]);
                }
                if((m+n)%2 == 1){
                    return leftMax;
                }else{
                    return (leftMax+rightMin)/2.0;
                }
            }
        }
        return  0.0;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值