LeetCode刷题记录:4. 寻找两个正序数组的中位数-Median of Two Sorted Arrays

LeetCode刷题记录:4. 寻找两个正序数组的中位数-Median of Two Sorted Arrays

题目

给定两个大小为 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

示例 3

输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000

示例 4

输入:nums1 = [], nums2 = [1]
输出:1.00000

示例 5

输入:nums1 = [2], nums2 = []
输出:2.00000

提示

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

链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays

解题思路

从复杂度为 O(log (m+n))可以想象的出此题应该是二分法的思想。在一个有序数组中,中位数仅受中间一个或是两个数字的影响,那么分成两个有序数组来看,我们仅需找到相应的四个数字来进行比较即可以得出相应结果。

java实现

这里留作思考,我认为我的思路也是遵循 O(log (min(m,n)))

个人版(二分法)

执行用时:3 ms, 在所有 Java 提交中击败了82.41%的用户

class Solution {
    public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            return findMedianSortedArrays(nums2, nums1);
        }
        int shorterArrayFlag = 0;
        int longerArrayFlag = (nums1.length+nums2.length) / 2;
        int path = (nums1.length + 1) / 2;
        boolean evenFlag = (nums1.length+nums2.length) % 2 == 0 ? true : false;
        int shorterFlagLeftValue,shorterFlagRightValue,longerFlagLeftValue,longerFlagRightValue;
        while(true){
            shorterFlagLeftValue = shorterArrayFlag <= 0 ? Integer.MIN_VALUE : nums1[shorterArrayFlag - 1];
            shorterFlagRightValue = shorterArrayFlag >= nums1.length ? Integer.MAX_VALUE : nums1[shorterArrayFlag];
            longerFlagLeftValue = longerArrayFlag <= 0 ? Integer.MIN_VALUE : nums2[longerArrayFlag - 1];
            longerFlagRightValue = longerArrayFlag >= nums2.length ? Integer.MAX_VALUE : nums2[longerArrayFlag];
            if (shorterFlagLeftValue <= longerFlagRightValue && longerFlagLeftValue <= shorterFlagRightValue) {
                return evenFlag ? evenArrayResult(shorterFlagLeftValue, longerFlagLeftValue, shorterFlagRightValue, longerFlagRightValue) : oddArrayResult(shorterFlagRightValue, longerFlagRightValue);
            } else if (shorterFlagLeftValue > longerFlagRightValue) {
                shorterArrayFlag -= path;
                longerArrayFlag += path;
                path = (path + 1) / 2;
            } else if (longerFlagLeftValue > shorterFlagRightValue) {
                shorterArrayFlag += path;
                longerArrayFlag -= path;
                path = (path + 1) / 2;
            } 
        }
    }

    public static double oddArrayResult(int shorterFlagRightValue, int longerFlagRightValue) {
        return shorterFlagRightValue < longerFlagRightValue ? (double) shorterFlagRightValue : (double) longerFlagRightValue;
    }

    public static double evenArrayResult(int shorterFlagLeftValue, int longerFlagLeftValue, int shorterFlagRightValue, int longerFlagRightValue) {
        int leftValue = shorterFlagLeftValue > longerFlagLeftValue ? shorterFlagLeftValue : longerFlagLeftValue;
        int rightValue = shorterFlagRightValue < longerFlagRightValue ? shorterFlagRightValue : longerFlagRightValue;
        return (double) (leftValue + rightValue) / 2;
    }
}

官方

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            return findMedianSortedArrays(nums2, nums1);
        }

        int m = nums1.length;
        int n = nums2.length;
        int left = 0, right = m;
        // median1:前一部分的最大值
        // median2:后一部分的最小值
        int median1 = 0, median2 = 0;

        while (left <= right) {
            // 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]
            // 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]
            int i = (left + right) / 2;
            int j = (m + n + 1) / 2 - i;

            // nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]
            int nums_im1 = (i == 0 ? Integer.MIN_VALUE : nums1[i - 1]);
            int nums_i = (i == m ? Integer.MAX_VALUE : nums1[i]);
            int nums_jm1 = (j == 0 ? Integer.MIN_VALUE : nums2[j - 1]);
            int nums_j = (j == n ? Integer.MAX_VALUE : nums2[j]);

            if (nums_im1 <= nums_j) {
                median1 = Math.max(nums_im1, nums_jm1);
                median2 = Math.min(nums_i, nums_j);
                left = i + 1;
            } else {
                right = i - 1;
            }
        }

        return (m + n) % 2 == 0 ? (median1 + median2) / 2.0 : median1;
    }
}

优质答案

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m,n,i,j,k;
        int max =1000000;
        double ans, ansl;
        ans = 0;
        ansl = 0;
        m = nums1.length;
        n = nums2.length;
        int mid = (m+n)/2;
        if(m == 0)
        {
            if(n%2==1)
                return (double)nums2[mid];
            else
                return ((double)nums2[mid]+(double)nums2[mid-1])/2;
        }
        else if(n == 0)
        {
            if(m%2==1)
                return nums1[mid];
            else
                return ((double)nums1[mid]+(double)nums1[mid-1])/2;
        }
        else if((m+n)%2==1)
        {
            i=0;
            j=0;
            for(k=0;k<=mid;k++){
                if(nums1[i]<nums2[j])
                {
                    ans = nums1[i];
                    if(i<m-1)
                        i++;
                    else
                        nums1[i]=max;
                }
                else
                {
                    ans = nums2[j];
                    if(j<n-1)
                        j++;
                    else
                        nums2[j]=max;
                }
            }
            return ans;
        }
        else
        {
            i=0;
            j=0;
            for(k=0;k<=mid;k++){
                if(nums1[i]<nums2[j])
                {
                    ansl = ans;
                    ans = nums1[i];
                    if(i<m-1)
                        i++;
                    else
                        nums1[i]=max;
                }
                else
                {
                    ansl = ans;
                    ans = nums2[j];
                    if(j<n-1)
                        j++;
                    else
                        nums2[j]=max;
                }
            }
            return (ans+ansl)/2;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值