LeetCode 力扣 热题 100道(四)寻找两个正序数组的中位数(C++)

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

给定两个大小分别为 mn 的正序(从小到大)数组 nums1nums2。请你找出并返回这两个正序数组的 中位数 。算法的时间复杂度应该为 O(log (m+n))

方法一:(不推荐)

cpp 复制代码
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        vector<int> merged;
        double median = 0;
        int i=0,j=0;
        while(i < nums1.size() && j < nums2.size()){
            if(nums1[i] < nums2[j]){
                merged.push_back(nums1[i]);
                i++;
            } else {
                merged.push_back(nums2[j]);
                j++;
            }
        }
        
        while (i < nums1.size()) {
            merged.push_back(nums1[i]);
            i++;
        }

        while(j < nums2.size()){
            merged.push_back(nums2[j]);
            j++;
        }

        int n = merged.size();
        if (n % 2 == 0) {
            median = (merged[n / 2 - 1] + merged[n / 2]) / 2.0;
        } else {
            median = merged[n / 2];
        }

        return median;
    }
};
  • 使用双指针 ij 分别指向 nums1nums2 的起始位置。
  • 比较 nums1[i]nums2[j],将较小的元素放入 merged 数组。
  • 将较小元素的指针后移(即,继续检查数组中的下一个元素)。
  • 直到一个数组被完全遍历。
  • 如果 nums1 还有剩余元素,将其直接追加到 merged 中。
  • 同样地,如果 nums2 还有剩余元素,也直接追加到 merged 中。
  • 这样,merged 就是一个完整的、合并后的有序数组。
  • 首先获取 merged 数组的大小 n
  • 如果 n 是偶数:
    • 中位数是数组中间两个数的平均值,即 (merged[n / 2 - 1] + merged[n / 2]) / 2.0
  • 如果 n 是奇数:
    • 中位数是数组的中间元素,即 merged[n / 2]

方法二:

cpp 复制代码
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        // 确保 nums1 是较短的数组
        if (nums1.size() > nums2.size()) {
            return findMedianSortedArrays(nums2, nums1);
        }

        int m = nums1.size();
        int n = nums2.size();
        int totalLeft = (m + n + 1) / 2;

        int left = 0, right = m;
        while (left < right) {
            int i = left + (right - left) / 2;
            int j = totalLeft - i;

            if (nums1[i] < nums2[j - 1]) {
                // i 需要右移
                left = i + 1;
            } else {
                // i 需要左移
                right = i;
            }
        }

        int i = left;
        int j = totalLeft - i;

        // 左半部分的最大值
        int nums1LeftMax = (i == 0) ? INT_MIN : nums1[i - 1];
        int nums2LeftMax = (j == 0) ? INT_MIN : nums2[j - 1];
        int leftMax = max(nums1LeftMax, nums2LeftMax);

        // 如果总长度是奇数
        if ((m + n) % 2 == 1) {
            return leftMax;
        }

        // 右半部分的最小值
        int nums1RightMin = (i == m) ? INT_MAX : nums1[i];
        int nums2RightMin = (j == n) ? INT_MAX : nums2[j];
        int rightMin = min(nums1RightMin, nums2RightMin);

        // 如果总长度是偶数,返回平均值
        return (leftMax + rightMin) / 2.0;
    }
};
1. 确保 nums1 是较短的数组

通过判断 nums1nums2 的长度,始终在较短的数组上进行二分查找。

2. 使用二分查找调整分割点
  • i 是在 nums1 的分割点,j 是在 nums2 的分割点。
  • i + j = totalLeft,保证左半部分元素总数等于右半部分。
  • 根据条件调整 i
    • 如果 nums1[i] < nums2[j - 1],说明 i 需要右移。
    • 如果 nums1[i] >= nums2[j - 1],说明 i 满足条件或需要左移。
3. 计算中位数
  • 左半部分最大值为:max(nums1[i-1], nums2[j-1])
  • 右半部分最小值为:min(nums1[i], nums2[j])
  • 如果总长度为奇数,直接返回左半部分最大值。
  • 如果总长度为偶数,返回左右半部分最大值与最小值的平均值。
相关推荐
多吃蔬菜!!!2 小时前
排序算法C语言实现
数据结构
零叹2 小时前
篇章六 数据结构——链表(二)
数据结构·链表·linkedlist
CM莫问2 小时前
<论文>(微软)WINA:用于加速大语言模型推理的权重感知神经元激活
人工智能·算法·语言模型·自然语言处理·大模型·推理加速
_r0bin_4 小时前
前端面试准备-7
开发语言·前端·javascript·fetch·跨域·class
zhang98800004 小时前
JavaScript 核心原理深度解析-不停留于表面的VUE等的使用!
开发语言·javascript·vue.js
计信金边罗4 小时前
是否存在路径(FIFOBB算法)
算法·蓝桥杯·图论
MZWeiei4 小时前
KMP 算法中 next 数组的构建函数 get_next
算法·kmp
Fanxt_Ja5 小时前
【JVM】三色标记法原理
java·开发语言·jvm·算法
蓝婷儿5 小时前
6个月Python学习计划 Day 15 - 函数式编程、高阶函数、生成器/迭代器
开发语言·python·学习
love530love6 小时前
【笔记】在 MSYS2(MINGW64)中正确安装 Rust
运维·开发语言·人工智能·windows·笔记·python·rust