Лучшее, что я мог бы придумать, - это создать матрицу сумм каждой пары, а затем объединить строки, а-ля сортировка слиянием. Я чувствую, что мне не хватает некоторого простого понимания, которое покажет гораздо более эффективное решение.
Мой алгоритм, на Хаскеле:
matrixOfSums list = [[a+b | b <- list, b >= a] | a <- list]
sortedSums = foldl merge [] matrixOfSums
--A normal merge, save that we remove duplicates
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = case compare x y of
LT -> x:(merge xs (y:ys))
EQ -> x:(merge xs (dropWhile (==x) ys))
GT -> y:(merge (x:xs) ys)
Я обнаружил небольшое улучшение, более подходящее для ленивого потокового кодирования. Вместо того, чтобы объединять столбцы попарно, объединяйте их все сразу. Преимущество в том, что вы сразу начинаете получать элементы списка.
-- wide-merge does a standard merge (ala merge-sort) across an arbitrary number of lists
-- wideNubMerge does this while eliminating duplicates
wideNubMerge :: Ord a => [[a]] -> [a]
wideNubMerge ls = wideNubMerge1 $ filter (/= []) ls
wideNubMerge1 [] = []
wideNubMerge1 ls = mini:(wideNubMerge rest)
where mini = minimum $ map head ls
rest = map (dropWhile (== mini)) ls
betterSortedSums = wideNubMerge matrixOfSums
Однако, если вы знаете, что собираетесь использовать все суммы, и получение некоторых из них не имеет никакого преимущества, используйте 'foldl merge []
', поскольку это быстрее.