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

172 阅读2分钟

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”

一、题目描述

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

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

二、思路分析

  • 首先正序数组说明数组是排过序的,要求时间复杂度O(log (m+n)),很明显需要用二分查找 ,不了解的,可以点击看我之前写的文章。
    • 中位数的概念是指数组中间的数,所以分两种情况
    • 数组长度为奇数,则返回中间的数即可
    • 数组长度为偶数,需要返回中间两个数和的平均数

三、AC 代码:

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;
    }
}


四、总结:

  • 好了,代码撸完,我们总结一下
    • 这道题的重点在于二分法的运用,以及对于中位数的理解
    • 细节,要注意先把数组长度短的放在前面,这样以短的进行二分时间复杂度会更快

最后这个算法是Leetcode的第四题,也是热题100的第四题,去年我刷了热题100用时一个月左右,接下来我会继续更新,小伙伴可以点一下关注,如果你也在刷热题100的话。