Leetcode-4.Median of Two Sorted Arrays

本文介绍了一种在O(log(m+n))的时间复杂度内找到两个有序数组中位数的方法。通过调整两个指针的位置,逐步缩小搜索范围直至找到中位数。此外,还提供了一个基于查找第k小元素的解决方案。

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

Problem Description :
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)).

This link elaborate on the idea
Codes:

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        if (m > n) return findMedianSortedArrays(nums2, nums1);
        int imin = 0, imax = m;
        int i = 0, num1, num2;
        while (imin <= imax)
        {
            int i = (imin + imax) / 2;
            int j =((m + n + 1) >> 1) - i;

            if (j > 0 && i < m && nums2[j - 1] > nums1[i])
                imin = i + 1;
            else if (i > 0 && j < n && nums1[i - 1] > nums2[j])
                imax = i - 1;
            else {
                if (i == 0)
                    num1 = nums2[j - 1];
                else if (j == 0)
                    num1 = nums1[i - 1];
                else num1 = max(nums1[i - 1], nums2[j - 1]);

                if ((m + n) % 2 == 1)
                    return num1;
                if (i == m)
                    num2 = nums2[j];
                else if (j == n)
                    num2 = nums1[i];
                else 
                    num2 = min(nums1[i], nums2[j]);
                return (num1 + num2) / 2.0;
            }
        }
     }  

Another Log( m + n) solution:

Let me add some interpretation of the find kth function based on my understanding

We have two arrays:

nums1[0], nums1[1]….nums1[m - 1];

nums2[0], nums2[2]….nums2[n - 1];

the result after merging:

num[0],num[1],num[2]…num[m + n - 1];

Let‘s compare nums1[k / 2 - 1] and nums2[k / 2 - 1]

if nums1[k / 2 - 1] < nums2 [k / 2 - 1]

then the nums1[k / 2 - 1] and it’s left side elements must smaller than kth number in num arrary(num[k - 1]).
Why? Assume that nums1[k / 2 - 1] == num[k - 1];

Let’s count the number of elements which smaller than nums1[k / 2 - 1].

Consider an extreme case : nums1[0]….nums1[k / 2 - 2] and nums2[0]…nums2[k / 2 - 2] smaller than nums1[k / 2 - 1];

In this special case, we only have k / 2 - 1 + k / 2 - 1 = k - 2 elements smaller than the nums1[k / 2 - 1]. so nums1[k / 2 - 1] only can be (k - 1)th smallest number (num[k - 2]); So, it’s a contradiction with our assumption.

And now we could say, The num[k / 2 - 1] and it’s left side elements must smaller than the Kth smallest number. so we could remove the elements which in this range and shrink the problem set. same idea when nums1[k / 2 - 1] > nums2 [k / 2 - 1]. we could remove the elements in the nums2;

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    int m = nums1.size(), n = nums2.size();
    int k = (m + n) / 2;
    int num1 = findKth(nums1, 0, m, nums2, 0, n, k + 1);
    if ((n + m) % 2 == 0)
    {
        int num2 = findKth(nums1, 0, m, nums2, 0, n, k);
        return (num1 + num2) / 2.0;
    }
    else return num1;
}
int findKth(vector<int> & nums1, int nums1_left, int nums1_right, vector<int> & nums2, int nums2_left, int nums2_right, int k)
{
    int m = nums1_right - nums1_left;
    int n = nums2_right - nums2_left;
    if (m > n) return findKth(nums2, nums2_left, nums2_right, nums1, nums1_left, nums1_right, k);
    else if (m == 0)
        return nums2[nums2_left + k - 1];
    else if (k == 1)
        return min(nums1[nums1_left], nums2[nums2_left]);
    else {
        int s1LeftCount = min (k / 2, m);
        int s2LeftCount = k - s1LeftCount;
        if (nums1[nums1_left + s1LeftCount - 1] == nums2[nums2_left + s2LeftCount - 1])
            return nums1[nums1_left + s1LeftCount - 1];
        else if (nums1[nums1_left + s1LeftCount - 1] < nums2[nums2_left + s2LeftCount - 1])
            return findKth(nums1, nums1_left + s1LeftCount, nums1_right, nums2, nums2_left, nums2_right, k - s1LeftCount);
        else
        return findKth(nums1, nums1_left, nums1_right, nums2, nums2_left + s2LeftCount, nums2_right, k - s2LeftCount);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值