For example, lets take l1={6,4,3,1} and l2={5,4,1}. Plot them as horizontal and vertical lines on 2D plane.
Then points of interest are all intersections. We should report those intersections in order an imaginary sweep line moving from (inf, inf) to (0, 0) touches them. Notice that a point lying on the horizontal line can't be reported earlier than another point on the same line which is righter. So for each horizontal line we must check only rightmost point. From all those points, we must choose one with the greatest sum of coordinates. This can be done with heap data structure.
Initially, we place all points lying on the rightmost vertical line into the heap. Then we extract the top point from the heap, yield it and finally put its left neighbour into the heap (if it has one). So heap always contains at most len(l1) elements, and every new generated point cost us O(log(len(l1))). Solution can be improved if we choose l1 to be smallest list from two given.
Here is example solution:
import heapq
a = [("a", 6), ("b", 4), ("c", 3), ("d", 1)]
b = [("e", 5), ("f", 5), ("g", 4), ("h", 2)]
class Pair:
def __init__(self, i, j, value):
self.i = i
self.j = j
self.value = value
def __cmp__(self, other):
return other.value - self.value
def solution(a, b):
heap = []
for i in range(len(a)):
heapq.heappush(heap, Pair(i, 0, a[i][1] + b[0][1]))
while len(heap) > 0:
pair = heapq.heappop(heap)
yield (a[pair.i], b[pair.j], pair.value)
if pair.j + 1 < len(b):
heapq.heappush(heap, Pair(pair.i, pair.j + 1, a[pair.i][1] + b[pair.j + 1][1]))
for (a, b, value) in solution(a, b):
print ("%s %s -> %d" % (a, b, value))
Things get worse when we are going into higher dimensions (more than 2 lists to combine). It can be solved on top of the 2D solution, with memoization, so we first build an answer for l1,l2 as lazy-list-like data structure, and then apply the same algorithm again, for this memoized list and l3 as arguments, and so on. One last step that must be taken - we should either always use array with smaller length as l1, or get rid of pushing all elements of l1 into heap in the beginning.
Complete code example for N lists here, as it too long.