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])
  • 如果总长度为奇数,直接返回左半部分最大值。
  • 如果总长度为偶数,返回左右半部分最大值与最小值的平均值。
相关推荐
kylezhao20197 分钟前
C# 中的 SOLID 五大设计原则
开发语言·c#
王老师青少年编程14 分钟前
2024年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)
c++·题解·真题·csp·信奥赛·csp-s·提高组
凡人叶枫42 分钟前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
CSDN_RTKLIB43 分钟前
使用三方库头文件未使用导出符号情景
c++
zheyutao1 小时前
字符串哈希
算法
春日见1 小时前
车辆动力学:前后轮车轴
java·开发语言·驱动开发·docker·计算机外设
A尘埃1 小时前
保险公司车险理赔欺诈检测(随机森林)
算法·随机森林·机器学习
锐意无限1 小时前
Swift 扩展归纳--- UIView
开发语言·ios·swift
低代码布道师1 小时前
Next.js 16 全栈实战(一):从零打造“教培管家”系统——环境与脚手架搭建
开发语言·javascript·ecmascript
念何架构之路1 小时前
Go进阶之panic
开发语言·后端·golang