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])
  • 如果总长度为奇数,直接返回左半部分最大值。
  • 如果总长度为偶数,返回左右半部分最大值与最小值的平均值。
相关推荐
Scc_hy7 分钟前
强化学习_Paper_1988_Learning to predict by the methods of temporal differences
人工智能·深度学习·算法
巷北夜未央8 分钟前
Python每日一题(14)
开发语言·python·算法
javaisC10 分钟前
c语言数据结构--------拓扑排序和逆拓扑排序(Kahn算法和DFS算法实现)
c语言·算法·深度优先
爱爬山的老虎11 分钟前
【面试经典150题】LeetCode121·买卖股票最佳时机
数据结构·算法·leetcode·面试·职场和发展
SWHL12 分钟前
rapidocr 2.x系列正式发布
算法
阳光_你好26 分钟前
请详细说明opencv/c++对图片缩放
c++·opencv·计算机视觉
杰克逊的黑豹33 分钟前
不再迷茫:Rust, Zig, Go 和 C
c++·rust·go
雾月5536 分钟前
LeetCode 914 卡牌分组
java·开发语言·算法·leetcode·职场和发展
想跑步的小弱鸡40 分钟前
Leetcode hot 100(day 4)
算法·leetcode·职场和发展
Fantasydg41 分钟前
DAY 35 leetcode 202--哈希表.快乐数
算法·leetcode·散列表