需要帮助提出我的算法中的缺陷的优雅修复

时间:2015-04-20 01:47:17

标签: c++ c algorithm

我正在练习接受一家大型在线零售商的采访,现在正试图为“两个排序数组的中位数”问题提出一个优雅的解决方案。我知道youtube上提出的解决方案,但我正在尝试编写另一种解决方案。我写了

include <stdio.h>

int M2SA ( int * A, int m, int * B, int n )
{
   /* Returns the median of two sorted arrays A and B of lengths m and n respectively. 
      Assumes A and B aren't both empty. 
   */ 
   int ida = 0, idb = 0, idmed = (m+n)/2;
   while ((ida + idb) != idmed)
   {
     if (A[ida] < B[idb])
        ++ida;
     else
        ++idb;
   }
   return (A[ida] < A[idb] ? A[ida] : B[idb]);
} 



int main()
{
    int arr1 [] = {1, 1, 59, 69};
    int arr2 [] = {-4, 0, 49, 59, 59, 59};
    printf("%d", M2SA(arr1, sizeof(arr1)/sizeof(int), arr2, sizeof(arr2)/sizeof(int)));
    return 0;
}

打印出正确答案(59),但我发现有一个缺陷,即我的算法仅在idmed不大于mn时才有效。例如,如果数组是{1}{69, 293, 393, 1923129},则在ida循环的第一次迭代后1等于while,因此第二次迭代while循环尝试访问A[1]。但是,我想不出一个简单的解决方法来添加到我的代码中。有一个简单的吗?

3 个答案:

答案 0 :(得分:3)

以下是对您的解决方案的优雅修复:

int ida = 0, idb = 0, idmed = (m + n) / 2;
while (ida < m && idb < n && ida + idb < idmed) {
    A[ida] < B[idb] ? ++ida : ++idb;
}
if (ida == m) return B[idmed - m];
if (idb == n) return A[idmed - n];
return A[ida] < B[idb] ? A[ida] : B[idb];

答案 1 :(得分:2)

基本上有3种情况需要考虑:

  1. 两个数组都没有被完全消耗。
  2. 第一个数组已消耗,中位数为第二个数组。
  3. 已消耗第二个数组,中位数位于第一个数组中。
  4. 实施必须了解这3个案例。 触发3种情况中的哪一种取决于输入数据。

    例如,如果所有较小的值都在数组1中,并且数组2中的较大值和数组1的长度短于数组2的长度,则数组1中的索引处于数组1的长度。所以访问它不是一个好主意。

    这是一个使用for循环而不是while的实现。我更喜欢在这里循环,因为更容易看到循环最终会终止。

    main()函数包含一组测试用例,它们触发上述所有三个代码路径。

    int 
    m2a
    ( _In_reads_(s1) const int * a1
    , int s1
    , _In_reads_(s2) const int *a2
    , int s2
    )
    {
        int mi = (s1 + s2) / 2;
        int ai1 = 0;
        int ai2 = 0;
        for (int i = 0; i < mi;i++)
        {
            if (ai1 < s1 && ai2 < s2)
            {
                if (a1[ai1] < a2[ai2])
                {
                    ai1++;
                }
                else
                {
                    ai2++;
                }
            }
            else
            {
                if (ai1 < s1)
                {
                    ai1++;
                }
                if (ai2 < s2)
                {
                    ai2++;
                }
            }
        }
        int result = 0;
        if (ai1 < s1 && ai2 < s2)
        {
            result = a1[ai1] < a2[ai2] ? a1[ai1] : a2[ai2];
        }
        else
        {
            if (ai1 < s1)
            {
                result = a1[ai1];
            }
            if (ai2 < s2)
            {
                result = a2[ai2];
            }
        }
        return result;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        {
            const int s1 = 4;
            const int s2 = 4;
            int a1[s1] = { 1, 2, 3, 4 };
            int a2[s2] = { 1, 2, 3, 4 };
            int m = m2a(a1, s1, a2, s2);
            printf("%d\n", m);
        }
        {
            const int s1 = 5;
            const int s2 = 4;
            int a1[s1] = { 5,6,7,8,9 };
            int a2[s2] = { 1, 2, 3, 4 };
            int m = m2a(a1, s1, a2, s2);
            printf("%d\n", m);
        }
        {
            const int s1 = 4;
            const int s2 = 5;
            int a1[s1] = { 1, 2, 3, 4 }; 
            int a2[s2] = { 5, 6, 7, 8, 9 };
            int m = m2a(a1, s1, a2, s2);
            printf("%d\n", m);
        }
        {
            const int s1 = 1;
            const int s2 = 5;
            int a1[s1] = { 99 };
            int a2[s2] = { 5, 6, 7, 8, 9 };
            int m = m2a(a1, s1, a2, s2);
            printf("%d\n", m);
        }
        {
            const int s1 = 5;
            const int s2 = 1;
            int a1[s1] = { 5, 6, 7, 8, 9 };
            int a2[s2] = { 99 }; 
            int m = m2a(a1, s1, a2, s2);
            printf("%d\n", m);
        }
    
        {
            const int s1 = 5;
            const int s2 = 5;
            int a1[s1] = { 1,1,1,1,1 };
            int a2[s2] = { 1,1,1,1,1 };
            int m = m2a(a1, s1, a2, s2);
            printf("%d\n", m);
        }
    
        {
            const int s1 = 5;
            const int s2 = 1;
            int a1[s1] = { 5, 6, 7, 8, 9 };
            int a2[s2] = { 3 };
            int m = m2a(a1, s1, a2, s2);
            printf("%d\n", m);
        }
        return 0;
    }
    

    修复剩余的bug。脑死亡“优雅”。如果你有3个案例,试图隐藏它是危险的。所以,循环体也显示了3个案例......

答案 2 :(得分:0)

也许你可以改变:

if (A[ida] < B[idb])

要:

if (ida < m && A[ida] < B[idb])

return (A[ida] < A[idb] ? A[ida] : B[idb]);

要:

return (ida < m && A[ida] < A[idb] ? A[ida] : B[idb]);