LeetCode:Median of Two Sorted Arrays(获取两个有序数组中的中间值)

4. Median of Two Sorted Arrays

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

我的解决方案,就是重新将数组A/B重新排序,然后获取中间值。

     public  double FindMedianSortedArrays(int[] nums1, int[] nums2)
        {
            int num1_length = nums1.Length;
            int num2_length = nums2.Length;
            int maxlength = num1_length > num2_length ? num1_length : num2_length;
            int[] newnums = new int[num1_length + num2_length];
            int target_length = 0;
            if (maxlength == 0) return 0.00d;
         
            for (int i = 0; i < maxlength; i++)
            {
                if (num1_length ==0|| num2_length ==0|| nums1[0] <= nums2[0]|| nums1[0] <= nums2[num2_length - 1])
                {
                    handleArray(ref nums1, ref newnums, ref target_length, i);
                    handleArray(ref nums2, ref newnums, ref target_length, i);
                }
                else
                {
                    handleArray(ref nums2, ref newnums, ref target_length, i);
                    handleArray(ref nums1, ref newnums, ref target_length, i);
                }
            }
            if (target_length % 2==0)
            {
                return Math.Round((Convert.ToDouble(newnums[target_length / 2 - 1] + newnums[target_length / 2]) / 2),2);
            }
            else
            {
                return Convert.ToDouble(newnums[target_length / 2]);
            }
        }

时间复杂度为O(m+n),显然还是不行。

Solution in LeetCode

Approach 1: Recursive Approach

 

 

要解决问题,首先我们得清楚了解median的含义

分成两块相同大小的块,而且其中一块大于另外一块。(如下图A,B)

如把A,B分别切分为相等的两块

left_A | right_A

A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]


left_B | right_B

B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]

假设A块的大小为m,B块的大小为n,那我们就可以得出

\text{len}(\text{left\_A}) = i, \text{len}(\text{right\_A}) = m - ilen(left_A)=i,len(right_A)=mi.

当i=0时,left_A为空;当i=m时,right_A为空。

同理,B块也是一样。

如果以下两个条件成立

  1. \text{len}(\text{left\_part}) = \text{len}(\text{right\_part})len(left_part)=len(right_part)

  2. \max(\text{left\_part}) \leq \min(\text{right\_part})max(left_part)≤min(right_part)

那么可以得出

 

接下来,我们逐一分析两个数组之间的情况,如果数组A,B如例子所示,那么就满足以下两个条件:

如A={2,3} B={1,4},i=(0+2)/2=1,j=(2+2+1)/2-1=1,B[0]=1<=A[1]=2 A[0]=2<=B[1]=4

这个时候,你会想问"为什么n必须大于等于m"?因为这样j的索引项出超出范围了。如A={2,3} B={4},i=1,j=1,那么b[1]就是出界了。

接下来,我们就按照[0,m]的范围i~j一直循环下去:

  1. 令imin=0,imax=m, 范围就是[0,m]

  2. 令i=(imin+imax)/2,j=(m+n+1)/2-i

  3. 我们接下来遇到以下三种情况:

    - B[j1]A[i] and \text{A}[i-1] \leq \text{B}[j]A[i1]B[j] ,也就是说我们已经找到目标i了。

    - B[j1]>A[i] ,意味着A块可能很小,我们需要增加i,去看一下B[j1]>A[i] 

    - A[i1]>B[j],意味着B块可能很小,我们需要减少i,再看看A[i1]>B[j]

  4. 如果i找到了,那么就可以返回结果了

          当m+n是偶数时,需要左边的Max_Left和右边的Min_Left的平均值。

         当m+n是奇数时,只需要拿左边的Max_Left即可,因为Median就在块中。

 

接下来,我需要考虑下特殊情况,如i=0/j=0/i=m/j=n的情况。

  • 当i=0时,也就是说A_Left为空,直接可以得出Max_Left=B[j-1]

  • 当j=0时,也就是说B_Left为空,直接可以得出Max_Right=A[i-1]

  • 当i=m时,也就是说A_Right为空,直接可以得出Max_Right=B[j]

  • 当j=n时,也就是说B_Right为空,直接可以得出Max_Right=A[i]

算法如下:

   public double FindMedianSortedArrays(int[] A, int[] B)
            {
                int m = A.Length;
                int n = B.Length;
                if (m > n)
                { // to ensure m<=n
                    int[] temp = A; A = B; B = temp;
                    int tmp = m; m = n; n = tmp;
                }
                int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
                while (iMin <= iMax)
                {
                    int i = (iMin + iMax) / 2;
                    int j = halfLen - i;
                    if (i < iMax && B[j - 1] > A[i])
                    {
                        iMin = i + 1; // i is too small
                    }
                    else if (i > iMin && A[i - 1] > B[j])
                    {
                        iMax = i - 1; // i is too big
                    }
                     else
                    { // i is perfect
                        int maxLeft = 0;
                        if (i == 0) { maxLeft = B[j - 1]; }
                        else if (j == 0) { maxLeft = A[i - 1]; }
                        else { maxLeft = Math.Max(A[i - 1], B[j - 1]); }
                        if ((m + n) % 2 == 1) { return maxLeft; }

                        int minRight = 0;
                        if (i == m) { minRight = B[j]; }
                        else if (j == n) { minRight = A[i]; }
                        else { minRight = Math.Min(B[j], A[i]); }

                        return (maxLeft + minRight) / 2.0;
                    }
                }
                return 0.0;
            }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值