How to find kth largest number in pairwise sums like setA + setB?

前端 未结 3 439
时光取名叫无心
时光取名叫无心 2021-01-12 19:32

Here are two integers set, say A and B and we can get another set C, in which every element is sum of element a in A and element b in B.

For example, A = {1,2}, B =

3条回答
  •  [愿得一人]
    2021-01-12 20:07

    If k is very close to 1 or N, any algorithm that generates the sorted sums lazily could simply be run until the kth or N-kth item pops out.

    In particular, I'm thinking of best-first search of the following space: (a,b) means the ath item from A, the first list, added to the bth from B, the second.

    Keep in a best=lowest priority queue pairs (a,b) with cost(a,b) = A[a]+B[b].

    Start with just (1,1) in the priority queue, which is the minimum.

    Repeat until k items popped: 
     pop the top (a,b)
     if a<|A|, push (a+1,b)
     if a=1 and b<|B|, push (a,b+1)
    

    This gives you a saw-tooth comb connectivity and saves you from having to mark each (a,b) visited in an array. Note that cost(a+1,b)>=cost(a,b) and cost(a,b+1)>=cost(a,b) because A and B are sorted.

    Here's a picture of a comb to show the successor generation rule above (you start in the upper left corner; a is the horizontal direction):

    |-------
    |-------
    |-------
    

    It's just best-first exploration of (up to) all |A|*|B| tuples and their sums.

    Note that the most possible items pushed before popping k is 2*k, because each item has either 1 or 2 successors. Here's a possible queue state, where items pushed into the queue are marked *:

    |--*----
    |-*-----
    *-------
    

    Everything above and to the left of the * frontier has already been popped.

    For the N-k case, do the same thing but with reversed priority queue order and exploration order (or, just negate and reverse the values, get the (N-k)th least, then negate and return the answer).

    See also: sorted list of pairwise sums on SO, or the Open problems project.

提交回复
热议问题