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

题目来源

4. 寻找两个正序数组的中位数 - 力扣(LeetCode)

题目描述

给定两个大小分别为 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
  • -10^6 <= nums1[i], nums2[i] <= 10^6

题目解析

这题目前没有想到 O(log(m+n)) 时间复杂度的解法,后面找机会看看官方题解。

我看到这题,会联想到归并排序里面合并两个有序数组的策略,而本题实际上不需要合并 nums1 和 nums2,只需要模拟合并比较过程即可。

由于我们需要找到 nums1 和 nums2 合并后有序数组的中位数,而中位数就是中间的数,因此我们可以先求出合并后数组的长度 len = nums1.length + nums2.length。

  • 如果 len 为奇数,那么中位数就是合并后数组的第 len / 2 的元素
  • 如果 len 为偶数,那么中位数就是合并后数组的第 len / 2 和 len / 2 + 1 的元素的平均数

为了代码逻辑简单,我们这里默认合并后数组的中间数有两个,分别记录于 midNum1 和 midNum2。

合并两个有序数组的过程如下:

定义一个变量 k,用于记录已经合并的元素个数,这里我们需要合并 len / 2 + 1 个数

定义变量 i 和 变量 j,分别指向 nums1 和 nums2 的索引位置,初始时都为 0。

我们需要不停地比较 nums1[i] 和 nums2[j],谁更小,则谁先被合并。

当然,也存在某个数组被先一步合并完的情况,此时需要做好越界判断。

  1. 若 i 越界,即 i >= nums1.length,则 j++
  2. 若 j 越界,即 j >= nums2.length,则 i++
  3. 若 nums1[i] <= nums2[j],则 i++
  4. 若 nums1[i] > nums2[j],则 j++

每发生一次合并,我们需要操作如下:

  1. midNum1 = midNum2
  2. 更新 midNum2 为合并的元素值

这样的话,最后 midNum1 和 midNum2 记录的就是最后被合并的两个元素值。

由于我们只合并 len / 2 + 1 次,因此最后合并的两个元素值就是完全合并后的大数组的中间两个元素值。

  • 如果 len % 2 == 0,那么结果就是 (midNum1 + midNum2) / 2
  • 如果 len % 2 != 0,那么结果就是 midNum2

C源码实现

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    int len = nums1Size + nums2Size;

    int i = 0;
    int j = 0;

    int midNum1 = -1;
    int midNum2 = -1;

    for (int k = 0; k <= len / 2; k++) {
        midNum1 = midNum2;
        if (i >= nums1Size) {
            midNum2 = nums2[j++];
        } else if (j >= nums2Size) {
            midNum2 = nums1[i++];
        } else if (nums1[i] <= nums2[j]) {
            midNum2 = nums1[i++];
        } else {
            midNum2 = nums2[j++];
        }
    }

    if (len % 2 == 0) {
        return (midNum1 + midNum2) / 2.0;
    } else {
        return midNum2;
    }
}

C++源码实现

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len = nums1.size() + nums2.size();

        int i = 0;
        int j = 0;

        int midNum1 = -1;
        int midNum2 = -1;

        for (int k = 0; k <= len / 2; k++) {
            midNum1 = midNum2;
            if (i >= nums1.size()) {
                midNum2 = nums2[j++];
            } else if (j >= nums2.size()) {
                midNum2 = nums1[i++];
            } else if (nums1[i] <= nums2[j]) {
                midNum2 = nums1[i++];
            } else {
                midNum2 = nums2[j++];
            }
        }

        if (len % 2 == 0) {
            return (midNum1 + midNum2) / 2.0;
        } else {
            return midNum2;
        }
    }
};

Java源码实现

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len = nums1.length + nums2.length;

        int i = 0;
        int j = 0;

        int midNum1 = -1;
        int midNum2 = -1;

        for (int k = 0; k <= len / 2; k++) {
            midNum1 = midNum2;
            if (i >= nums1.length) {
                midNum2 = nums2[j++];
            } else if (j >= nums2.length) {
                midNum2 = nums1[i++];
            } else if (nums1[i] <= nums2[j]) {
                midNum2 = nums1[i++];
            } else {
                midNum2 = nums2[j++];
            }
        }

        if (len % 2 == 0) {
            return (midNum1 + midNum2) / 2.0;
        } else {
            return midNum2;
        }
    }
}

Python源码实现

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        length = len(nums1) + len(nums2)

        i = 0
        j = 0

        midNum1 = -1
        midNum2 = -1

        for k in range(length // 2 + 1):
            midNum1 = midNum2
            if i >= len(nums1):
                midNum2 = nums2[j]
                j += 1
            elif j >= len(nums2):
                midNum2 = nums1[i];
                i += 1
            elif nums1[i] <= nums2[j]:
                midNum2 = nums1[i];
                i += 1
            else:
                midNum2 = nums2[j]
                j += 1

        if length % 2 == 0:
            return (midNum1 + midNum2) / 2.0
        else:
            return midNum2

JavaScript源码实现

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function (nums1, nums2) {
    const len = nums1.length + nums2.length;

    let i = 0;
    let j = 0;

    let midNum1 = -1;
    let midNum2 = -1;

    for (let k = 0; k <= len / 2; k++) {
        midNum1 = midNum2;
        if (i >= nums1.length) {
            midNum2 = nums2[j];
            j++;
        } else if (j >= nums2.length) {
            midNum2 = nums1[i];
            i++;
        } else if (nums1[i] <= nums2[j]) {
            midNum2 = nums1[i];
            i++;
        } else {
            midNum2 = nums2[j];
            j++;
        }
    }

    if (len % 2 == 0) {
        return (midNum1 + midNum2) / 2;
    } else {
        return midNum2;
    }
};
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值