【问题标题】:Finding median of two sorted arrays of different size查找两个不同大小的排序数组的中位数
【发布时间】:2016-06-26 02:59:27
【问题描述】:

我正在解决问题find median!

这里基本上我有三个疑问:

  1. 对于N == 1 and M is odd的情况
    不能直接找MO4( A[0], B[M/2], B[M/2 -1], B[M/2 +1])吗?
  2. 为什么我们将AB 两个数组都缩短为idxA
  3. 这个算法的时间复杂度如何O(logM + logN)
// A C++ program to
// find median of two sorted arrays of unequal sizes
#include <bits/stdc++.h>
using namespace std;

// A utility function to find median of two integers
float MO2(int a, int b)
{ return ( a + b ) / 2.0; }

// A utility function to find median of three integers
float MO3(int a, int b, int c)
{
    return a + b + c - max(a, max(b, c))
                     - min(a, min(b, c));
}

// A utility function to find median of four integers
float MO4(int a, int b, int c, int d)
{
    int Max = max( a, max( b, max( c, d ) ) );
    int Min = min( a, min( b, min( c, d ) ) );
    return ( a + b + c + d - Max - Min ) / 2.0;
}

// Utility function to find median of single array
float medianSingle(int arr[], int n)
{
    if (n == 0)
        return -1;
    if (n%2 == 0)
        return (arr[n/2] + arr[n/2-1])/2;
    return arr[n/2];
}

// This function assumes that N is smaller than or equal to M
// This function returns -1 if both arrays are empty
float findMedianUtil( int A[], int N, int B[], int M )
{
    // If smaller array is empty, return median from second array
    if (N == 0)
        return medianSingle(B, M);

    // If the smaller array has only one element
    if (N == 1)
    {
        // Case 1: If the larger array also has one element,
        // simply call MO2()
        if (M == 1)
            return MO2(A[0], B[0]);

        // Case 2: If the larger array has odd number of elements,
        // then consider the middle 3 elements of larger array
        // and the only element of smaller array.
        // Take few examples like following
        // A = {9}, B[] = {5, 8, 10, 20, 30} and
        // A[] = {1}, B[] = {5, 8, 10, 20, 30}
        if (M & 1)
            return MO2( B[M/2], MO3(A[0], B[M/2 - 1], B[M/2 + 1]) );

        // Case 3: If the larger array has even number of element,
        // then median will be one of the following 3 elements
        // ... The middle two elements of larger array
        // ... The only element of smaller array
        return MO3( B[M/2], B[M/2 - 1], A[0] );
    }

    // If the smaller array has two elements
    else if (N == 2)
    {
        // Case 4: If the larger array also has two elements,
        // simply call MO4()
        if (M == 2)
            return MO4(A[0], A[1], B[0], B[1]);

        // Case 5: If the larger array has odd number of elements,
        // then median will be one of the following 3 elements
        // 1. Middle element of larger array
        // 2. Max of first element of smaller array and element
        //    just before the middle in bigger array
        // 3. Min of second element of smaller array and element
        //    just after the middle in bigger array
        if (M & 1)
            return MO3 ( B[M/2],
                         max(A[0], B[M/2 - 1]),
                         min(A[1], B[M/2 + 1])
                       );

        // Case 6: If the larger array has even number of elements,
        // then median will be one of the following 4 elements
        // 1) & 2) The middle two elements of larger array
        // 3) Max of first element of smaller array and element
        //    just before the first middle element in bigger array
        // 4. Min of second element of smaller array and element
        //    just after the second middle in bigger array
        return MO4 ( B[M/2],
                     B[M/2 - 1],
                     max( A[0], B[M/2 - 2] ),
                     min( A[1], B[M/2 + 1] )
                   );
    }

    int idxA = ( N - 1 ) / 2;
    int idxB = ( M - 1 ) / 2;

    // if A[idxA] <= B[idxB], then median must exist in
    // A[idxA...] and B[...idxB]
    if (A[idxA] <= B[idxB] )
        return findMedianUtil(A + idxA, N/2 + 1, B, M - idxA );

    // if A[idxA] > B[idxB], then median must exist in
    // A[...idxA] and B[idxB...] */
    return findMedianUtil(A, N/2 + 1, B + idxA, M - idxA );
}

// A wrapper function around findMedianUtil().
// This function makes sure that smaller array is
// passed as first argument to findMedianUtil
float findMedian( int A[], int N, int B[], int M )
{
    if (N > M)
        return findMedianUtil( B, M, A, N );

    return findMedianUtil( A, N, B, M );
}

// Driver program to test above functions
int main()
{
    int A[] = {900};
    int B[] = {5, 8, 10, 20};

    int N = sizeof(A) / sizeof(A[0]);
    int M = sizeof(B) / sizeof(B[0]);

    printf("%f", findMedian( A, N, B, M ) );
    return 0;
}

【问题讨论】:

  • 您提供了未注释的代码 - 一般而言,这是一个糟糕的举动。 (您甚至似乎已经手动删除了 cmets。)我更希望在此问题演示中返回值的定义。你放弃了it is assumed that N is smaller than or equal to M。请编辑您的问题,并特别问 what 使您无法理解:两个/所有数组/范围都可能被仅在一个中找到的值缩短?缩短所有范围确实可以简化问题吗?
  • @greybeard 我在编辑时遇到问题。你能检查一下吗?
  • 无法回答,因为问题仍处于暂停状态:1. MO4( A[0], B[M/2], B[M/2 -1], B[M/2 +1]) 等于 MO2(B[M/2], MO3(A[0], B[M/2-1], B[M/2+1])) 知道 B[M/2]B 的精确中位数,它将始终被选为平均值之一MO4 中的术语。 2. 这是遵循分而治之的范式:将问题划分为子问题。在这里,您将两个数组向中位数缩短相等的数量。您不能将两个数组减半,因为它们的大小不同(因此中位数将不再位于范围的中间,即使算法返回错误的值)。
  • 我投票决定重新开放,因为这是一个质量很好的有效算法问题。
  • (虽然我认为这是因为错误的原因而被搁置(因此给出了一个无用的参考链接),请访问How do I ask a good question? 并尽可能提出最好的问题。(如@987654323 @ 没有评论这个问题,在@ 后面提到他的名字不会让他得到通知。据我所知,编辑会通知,嗯,“审查”)。任何人都可以使用“标志”请求主持人干预链接。)(如果需要拼写,我认为这个问题需要在回答之前进行改进。)

标签: c++ arrays algorithm


【解决方案1】:
  1. 知道B[M/2]B 的精确中位数,这两个表达式是等价的(即使用B[M/2-1] &lt;= B[M/2] &lt;= B[M/2+1]):

    using a:=A[0], b:=B[M/2], bm:=B[M/2-1], bp:=B[M/2+1]
    MO4(a, b, bm, bp)
    = 0.5 * (a + b + bm + bp - min(a, b, bm, bp) - max(a, b, bm, bp))
    = 0.5 * (b + (a + bm + bp - min(a, bm, bp) - max(a, bm, bp))
    = MO2(b, MO3(a, bm, bp))
    
  2. 这是遵循分而治之的范式:将问题划分为子问题。在这里,您将两个数组向中位数缩短相等的数量。您不能将两个数组减半,因为它们的大小不同(因此中位数将不再位于范围的中间,即使算法返回错误的值)。这个in this related question有更广泛的答案。

  3. 对于N &lt;= M的情况,不失一般性:

    T(N, M) :=
    | (N < 2 && M < 2)  O(1)
    | (N < 2 && M >= 2) T(M) = O(log M)
    | (N == 2)          T(M) = O(log M)
    | (otherwise)       1 + T(N - N/2, M - N/2)
    

    这里的T(N, M)findMedianUtilT(M) 在单个数组中查找中值的运行时。通常,您会得到log N 计数,直到您达到基本情况之一,此时最多留下O(log M) -> O(log N + log M)

    附带说明:O(log M + log N) 是写O(log max(N,M)) 的一种懒惰方式。对于N &lt;= M,这等于O(log M),因为在这种情况下O(log N)O(log M) 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    • 1970-01-01
    • 2016-09-02
    • 2018-06-28
    • 2013-01-28
    • 2014-10-12
    • 1970-01-01
    相关资源
    最近更新 更多