【问题标题】:Find the pair across 2 arrays with kth largest sum在 2 个数组中找到第 k 个总和的对
【发布时间】:2011-03-06 17:16:51
【问题描述】:

给定两个排序的数字数组,我们希望找到具有第 k 个最大可能和的对。一对是来自第一个数组的一个元素和来自第二个数组的一个元素。例如,使用数组

  • [2,3,5,8,13]
  • [4,8,12,16]

总和最大的对是:

  1. 13 + 16 = 29
  2. 13 + 12 = 25
  3. 8 + 16 = 24
  4. 13 + 8 = 21
  5. 8 + 12 = 20

所以总和第 4 大的对是 (13, 8)。如何找到最大可能和的对?

我预计解决方案可能涉及最小堆或最大堆。

【问题讨论】:

  • “这个问题模棱两可、含糊不清、不完整”——不再如此。投票重新开放。

标签: algorithm sorting


【解决方案1】:

这可以在O(k*logk) 中轻松完成。我只假设数组按降序排序,以简化符号。

这个想法很简单。我们将一一找到第 1 个、第 2 个、..、第 k 个最大值。但即使考虑对 (i, j),我们也需要同时选择 (i-1, j)(i, j-1),因为它们都大于或等于 (i, j)

这很像我们将所有 n*m 对推入堆中,然后删除 max k 次。只是我们不需要所有的n*m 对。

heap.add(pair(0, 0));  // biggest pair

// remove max k-1 times
for (int i = 0; i < k - 1; ++i) {
    // get max and remove it from the heap
    max = heap.popMax();

    // add next candidates
    heap.add(pair(max.i + 1, max.j));
    heap.add(pair(max.i, max.j + 1));
}

// get k-th maximum element
max = heap.popMax();
maxVal = a[max.i] + b[max.j];

需要考虑的一些事项。

  • 可以将重复的对添加到堆中,这可以通过哈希来防止。
  • 需要验证索引,例如那个max.i + 1 &lt; a.length

【讨论】:

  • @Nikita:感谢您的努力!我想知道你为什么不考虑 i+1 和第二个数组中的最大元素?我的意思是为什么 max.i+1 , max.j,而不是 max.i+1 和第二个数组中的第一个元素。
  • @TimeToCodeTheRoad (i+1, 0) 在我们处理 (i, 0) 时已经添加到堆中。我们已经处理了 (i, 0) 因为a[i]+b[0] &gt;= a[i] + b[j] (好吧,如果它们相等,我们可能没有,但你可以看到它在正确性方面没有任何改变。)
  • @Nikita:再次感谢!另外,为什么我们不考虑数组 A 的第一个元素和第二个数组的 j+1 个元素?我真的很感谢你的帮助。请帮助我
  • @Nikita:我想奖励你更多的分数,而不仅仅是选择你的答案。有什么办法吗? :)
  • @TimeToCodeTheRoad 和你第一条评论的情况一样,只是 i 和 j 切换了。同样的道理也适用。
【解决方案2】:

我知道你想要一个堆,但这不是最有效的解决方案,正如 phimuemue 指出的那样。

您可以 max_heap 两个数组,并在两个数组的根处设置一个迭代器。此时,您的总和最大。

现在,在每一步中,在两个指针的子节点和邻居节点中找到最大的未访问节点——这是下一个最大的和。将相应堆中的指针移到那里。

重复k次。

【讨论】:

  • 这句话“在每一步,取两个值中较小的一个并遍历它的子节点和邻居的最大值”真的听起来不错吗?以此为例,heap1 [7, 1, 2],heap2 [8, 6, 7]。毫无疑问,最大的总和是 7(来自 heap1)+ 8(来自 heap2)。但第二大的是 7(来自 heap1)+ 7(来自 heap2)而不是 2(来自 heap1)+ 8(来自 heap2)。问候!
  • 啊,你是对的。编辑了我的答案
  • 很难理解你在做什么!!是否可以显示一些伪代码以获得更好的清晰度。
【解决方案3】:

这是我的答案,我认为它运作良好,但有人能告诉我它的复杂性吗?

谢谢

int ksum( int a[], int n, int b[], int m, int maxk )
{

    std::vector<int> results;
    int* check = new int[m*n];
    memset( check, 0, n*m*sizeof(int) );

    int finali, finalj;
    int starti = 0, startj = 0;
    for( int k=1; k<maxk+1; ++k )
    {
        int max = 0;
        int maxi=n, maxj=m;
        for( int i=starti; i<n && i<k; ++i )
        {
            if( i>maxj )
                break;
            for( int j=i; j<m && j<k; ++j )
            {
                if( i>maxi && j>=maxj )
                    break;
                if( check[i*m+j] == 0 )
                {
                    int tmp = a[i]+b[j];
                    if( tmp>max )
                    {
                        max = tmp;
                        finali = i, finalj = j;
                    }
                    maxi = i, maxj = j;
                    break;
                }
            }
        }
        starti = finali;

        maxi=n, maxj=m;
        for( int j=startj; j<n && j<k; ++j )
        {
            if( j>maxi )
                break;
            for( int i=j; i<m && i<k; ++i )
            {
                if( j>maxj && i>=maxi )
                    break;
                if( check[i*m+j] == 0 )
                {
                    int tmp = a[i]+b[j];
                    if( tmp>max )
                    {
                        max = tmp;
                        finali = i, finalj = j;
                    }
                    maxi = i, maxj = j;
                    break;
                }
            }
        }
        startj = finalj;

        if( max > 0 )
        {
            check[finali*m+finalj] = 1;
            results.push_back( max );
        }
    }

    delete[] check;
    if( maxk > results.size() )
        return 0;
    else
        return results[maxk-1];
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[] = {10,8,6,4,1};
    int b[] = {9,6,3,2,1};
    int res = ksum( a, 5, b, 5, 9 );
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    • 1970-01-01
    相关资源
    最近更新 更多