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

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

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。算法的时间复杂度应该为 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;
    }
};
  • 使用双指针 i 和 j 分别指向 nums1 和 nums2 的起始位置。
  • 比较 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 是较短的数组

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

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])。
  • 如果总长度为奇数,直接返回左半部分最大值。
  • 如果总长度为偶数,返回左右半部分最大值与最小值的平均值。
相关推荐
程序猿乐锅9 小时前
万字详解Single-flight(单飞模式)
java·开发语言·分布式·后端·学习·single-flight
扶尔魔ocy9 小时前
【QT入门到晋级】用开源的自定义控件开发
c++·qt·自定义控件
AiNightVision9 小时前
无人机夜视模块如何选择?——从参数指标到系统集成的完整选型指南
人工智能·算法·计算机视觉·车载系统·无人机·视频·智能硬件
牧羊人.33310 小时前
卷积神经网络之VGG
人工智能·深度学习·神经网络·算法·cnn
akinggw10 小时前
libsherpacore - 基于 sherpa-onnx 的 C++ 语音交互静态库
c++·交互·语音识别
xiaoye-duck11 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(中):全量响应实现和测试
网络·c++·语言模型·chatgpt
揽星河..11 小时前
【C语言】指针
c语言·开发语言
小郎君65811 小时前
Vue 多标签页的加载态设计:为什么我没有用 Suspense 实现 PageLoading
vue.js·算法
小小数媒成员11 小时前
UGUI原理(一)
开发语言·游戏·unity·游戏引擎
JJJennie77711 小时前
MAI Gateway私有化部署全攻略:大模型网关如何接入?附架构图
算法·gateway·ai网关·魔芋ai