[LeetCode] median of two sorted arrays

本文探讨了在两个已排序的数组中找到中位数的高效算法,该算法的时间复杂度为O(log(m+n)),其中m和n分别是两个数组的长度。通过将问题转化为寻找第k小元素,利用二分查找的策略,文章提供了一个递归解决方案,并附带了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

分析

嗯这是一道算法导论的课后题。原来的课后题是找出两个有序数组中的第k小元素,这里的k变成中位数。在求中位数的时候有一个小技巧,可以涵盖奇数与偶数的情况。这里两个有序数组的长度分别为m和n,那么就是从m+n个数据中求中位数。那么这个中位数就是第(m+n+1)/2个数和第(m+n+2)/2个数的平均值。这个表达式包含奇数和偶数的情况。然后接下来的问题就转化为求两个有序数组的第(m+n+1)/2小元素和第(m+n+2)/2小元素。

两个有序数组数组求第k小数据,复杂度O(log(m+n)),肯定是要用到二分的。这里的二分的方式为:分别求两个数组的第k/2小元素,假如数组1的第k/2小元素小于数组2的第k/2小元素,那么数组1的前k/2个数据中不可能包含我们想要的第k小数据。然后讲数组1的前k/2个数据删除,求剩下的两个数组的第k-k/2小元素就好了。那么从剩下数组中选取第k-k/2小的元素,可以递归前面的方法。

简单来讲,两个数组假如合并成了一个,从前k个元素中删除k/2个,那么剩下的数组的第k-k/2小就是原来数组的第k小。我们通过比较两个数组的第k/2小来决定删除哪部分数据。

在写递归函数过程中,我们可以分别用i和j来表示数组1和数组2的开始位置,通过移动i和j来实现前面说的删除。然后可能会出现某数组的长度小于k/2的情况,不妨设数组1的长度小于k/2,那么我们就能知道数组2的前k/2个数据中不包含综合起来的第k小数据。于是删除数组2的前k/2个数据然后递归即可。

一个更加详细讲解的链接

代码

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        return (findkth(nums1,0,nums2,0,(m+n+1)/2)+findkth(nums1,0,nums2,0,(m+n+2)/2))/2.0;
    }
        
        int findkth(vector<int>& num1,int i,vector<int>& num2,int j,int k) {
            if(i>=num1.size()) return num2[j+k-1];
            if(j>=num2.size()) return num1[i+k-1];
            if(k==1) return min(num1[i],num2[j]);
            int temp1 = (i+k/2-1<num1.size())?num1[i+k/2-1]:INT_MAX;
            int temp2 = (j+k/2-1<num2.size())?num2[j+k/2-1]:INT_MAX;
            if(temp1<temp2) return findkth(num1,i+k/2,num2,j,k-k/2);
            else return findkth(num1,i,num2,j+k/2,k-k/2);
        }
        
    
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值