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])
  • 如果总长度为奇数,直接返回左半部分最大值。
  • 如果总长度为偶数,返回左右半部分最大值与最小值的平均值。
相关推荐
前进之路96 小时前
Leetcode每日一练--28
leetcode
用户6605307619626 小时前
UFlow:像素级工业零件异常检测 Normalized Flow 方法
算法
aerror7 小时前
json转excel xlsx文件
开发语言·python·json
爱吃烤鸡翅的酸菜鱼7 小时前
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
java·算法
workflower7 小时前
软件工程的知识领域
开发语言·算法·软件工程·个人开发·结对编程
JoannaJuanCV7 小时前
error: can‘t find Rust compiler
开发语言·后端·rust
budingxiaomoli7 小时前
算法--双指针二
算法
做科研的周师兄7 小时前
【机器学习入门】8.2 主成分分析:一文吃透主成分分析(PCA)—— 从原理到核心逻辑
人工智能·算法·决策树·机器学习·流程图
LeeZhao@7 小时前
【具身智能】具身机器人VLA算法入门及实战(四):具身智能VLA技术行业进展
人工智能·算法·机器人
郏国上7 小时前
node.js上传图片接口
开发语言·node.js