力扣 寻找两个正序数组的中位数

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

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

算法的时间复杂度应该为 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

代码

cpp 复制代码
#include <vector>
#include <algorithm> // 用于min函数
using namespace std;

class Solution {
private:
    // 实现找两个数组中第k小的元素(修正后)
    int getKthNum(vector<int>& nums1, vector<int>& nums2, int k) {
        int m = nums1.size();
        int n = nums2.size();
        int offset1 = 0; // nums1的起始偏移量
        int offset2 = 0; // nums2的起始偏移量

        while (true) {
            // 若nums1已遍历完,直接返回nums2中第k个元素
            if (offset1 == m) {
                return nums2[offset2 + k - 1];
            }
            // 若nums2已遍历完,直接返回nums1中第k个元素
            if (offset2 == n) {
                return nums1[offset1 + k - 1];
            }
            // 若k=1,返回两个数组当前起始位置的较小值
            if (k == 1) {
                return min(nums1[offset1], nums2[offset2]);
            }

            // 计算本次要比较的位置(避免越界)
            int index1 = min(offset1 + k / 2 - 1, m - 1);
            int index2 = min(offset2 + k / 2 - 1, n - 1);

            // 比较两个位置的值,排除较小部分的元素
            if (nums1[index1] <= nums2[index2]) {
                // 排除nums1中offset1到index1的元素,更新k和offset1
                k -= (index1 - offset1 + 1);
                offset1 = index1 + 1;
            } else {
                // 排除nums2中offset2到index2的元素,更新k和offset2
                k -= (index2 - offset2 + 1);
                offset2 = index2 + 1;
            }
        }
    }

public:
    // 主函数:计算两个正序数组的中位数
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int total = nums1.size() + nums2.size();
        if (total % 2 == 1) {
            // 总元素为奇数,返回中间的元素(第(total+1)/2小)
            return getKthNum(nums1, nums2, (total + 1) / 2);
        } else {
            // 总元素为偶数,返回中间两个元素的平均值
            int ret1 = getKthNum(nums1, nums2, total / 2);
            int ret2 = getKthNum(nums1, nums2, total / 2 + 1);
            return (ret1 + ret2) / 2.0; // 修正笔误:=改为+
        }
    }
};

复杂度分析

每次迭代将k减半,最多执行log(m+n)次,因此时间复杂度为O(log(m+n)),满足题目要求。空间复杂度为O(1),仅使用常量额外空间。

常见疑问

  • 为什么比较k/2的位置?
    这样可以确保每次至少排除k/2个元素,快速缩小问题规模。
  • 如何处理数组越界?
    通过min(offset + k/2 -1, 数组长度-1)确保索引有效。
  • 为何偶数情况要调用两次函数?
    因为中位数由两个数决定,需分别找到第k/2和第k/2+1小的数。
相关推荐
一匹电信狗8 小时前
【LeetCode_547_990】并查集的应用——省份数量 + 等式方程的可满足性
c++·算法·leetcode·职场和发展·stl
鱼跃鹰飞9 小时前
Leetcode会员尊享100题:270.最接近的二叉树值
数据结构·算法·leetcode
梵刹古音10 小时前
【C语言】 函数基础与定义
c语言·开发语言·算法
筵陌10 小时前
算法:模拟
算法
We་ct10 小时前
LeetCode 205. 同构字符串:解题思路+代码优化全解析
前端·算法·leetcode·typescript
renhongxia111 小时前
AI算法实战:逻辑回归在风控场景中的应用
人工智能·深度学习·算法·机器学习·信息可视化·语言模型·逻辑回归
CoderCodingNo11 小时前
【GESP】C++四级/五级练习题 luogu-P1223 排队接水
开发语言·c++·算法
民乐团扒谱机11 小时前
【AI笔记】精密光时频传递技术核心内容总结
人工智能·算法·光学频率梳
CoderCodingNo11 小时前
【GESP】C++五级/四级练习题 luogu-P1413 坚果保龄球
开发语言·c++·算法
2301_8223663512 小时前
C++中的命令模式变体
开发语言·c++·算法