您有一个升序的数字列表,您可以想到的最有效的算法是获取该列表中每两个数字的总和的升序列表。 结果列表中的重复项无关紧要,如果您愿意,可以删除它们或避免使用它们。

要清楚,我对算法很感兴趣。 您可以随意使用您喜欢的任何语言和范例发布代码。

===============>>#1 票数:12 已采纳

编辑截至2018年:您可能应该停止阅读此内容。 (但我不能删除它,因为它被接受。)

如果你写出这样的总和:

1 4  5  6  8  9
---------------
2 5  6  7  9 10
  8  9 10 12 13
    10 11 13 14
       12 14 15
          16 17
             18

你会注意到,因为M [i,j] <= M [i,j + 1]和M [i,j] <= M [i + 1,j],那么你只需要检查左上角“角落“并选择最低的角落。

例如

  • 只有1个左上角,挑2
  • 只有1,选择5
  • 6或8,选6
  • 7或8,选7
  • 9或8,挑8
  • 9或9,选择两个:)
  • 10或10或10,全选
  • 12或11,选11
  • 12或12,选择两者
  • 13或13,选择两者
  • 14或14,选择两者
  • 15或16,选15
  • 只有1,选16
  • 只有1,选17
  • 只有1,选18

当然,当你有很多左上角时,这个解决方案就会变成现实。

我很确定这个问题是Ω(n²),因为你必须计算每个M [i,j]的总和 - 除非有人有更好的求和算法:)

===============>>#2 票数:4

而不是编码出来,我想我会逐步伪代码并解释我的逻辑,以便更好的程序员可以在必要时在我的逻辑中挖洞。

在第一步,我们从数字长度为n的列表开始。 对于每个数字,我们需要创建一个长度为n-1的列表,因为我们没有为自己添加数字。 最后,我们有一个关于在O(n ^ 2)时间内生成的n个排序列表的列表。

step 1 (startinglist) 
for each number num1 in startinglist
   for each number num2 in startinglist
      add num1 plus num2 into templist
   add templist to sumlist
return sumlist 

在步骤2中,因为列表是按设计排序的(向排序列表中的每个元素添加一个数字,列表仍然会被排序),我们可以通过将每个列表合并在一起而不是合并整个批次来简单地进行合并。 最后这应该花费O(n ^ 2)时间。

step 2 (sumlist) 
create an empty list mergedlist
for each list templist in sumlist
   set mergelist equal to: merge(mergedlist,templist)
return mergedlist

然后合并方法将是正常的合并步骤,并进行检查以确保没有重复的总和。 我不会写出来因为任何人都可以查找mergesort。

所以这是我的解决方案。 整个算法的时间为O(n ^ 2)。 随意指出任何错误或改进。

===============>>#3 票数:2

你可以用python中的两行来完成这个

allSums = set(a+b for a in X for b in X)
allSums = sorted(allSums)

这个的成本是迭代的n ^ 2(可能是集合的额外对数因子?)和排序的s * log(s),其中s是集合的大小。

例如,如果X = [1,2,4,...,2 ^ n],则该集合的大小可以与n *(n-1)/ 2一样大。 因此,如果您想生成此列表,则在最坏的情况下至少需要n ^ 2/2,因为这是输出的大小。

但是,如果要选择结果的前k个元素,可以使用Frederickson和Johnson对已排序的X + Y矩阵的选择算法在O(kn)中执行此操作( 请参阅此处了解详细信息) 虽然这可以通过重复使用计算并在此集合中获得高效的生成器来修改以在线生成它们。

@deuseldorf,Peter有一些混淆(n!)我严重怀疑deuseldorf是指“n factorial”,而只是“n,(非常激动)!”

===============>>#4 票数:1

这个问题一直困扰着我的大脑一天。 真棒。

无论如何,你不能轻易地摆脱它的n ^ 2性质,但是你可以通过合并做得更好,因为你可以绑定范围来插入每个元素。

如果查看生成的所有列表,它们具有以下形式:

(a[i], a[j]) | j>=i

如果你翻转90度,你会得到:

(a[i], a[j]) | i<=j

现在,合并过程应该采用两个列表ii+1 (对应于第一个成员总是a[i]a[i+1] ),你可以将范围绑定到insert元素(a[i + 1], a[j])通过(a[i], a[j])的位置和(a[i + 1], a[j + 1])的位置进入列表i

这意味着您应该在j方面进行反向合并。 我不知道(还)你是否可以在j利用这个,但似乎有可能。

===============>>#5 票数:1

在SQL中:

create table numbers(n int not null)
insert into numbers(n) values(1),(1), (2), (2), (3), (4)


select distinct num1.n+num2.n sum2n
from numbers num1
inner join numbers num2 
    on num1.n<>num2.n
order by sum2n

C#LINQ:

List<int> num = new List<int>{ 1, 1, 2, 2, 3, 4};
var uNum = num.Distinct().ToList();
var sums=(from num1 in uNum
        from num2 in uNum 
        where num1!=num2
        select num1+num2).Distinct();
foreach (var s in sums)
{
    Console.WriteLine(s);
}

===============>>#6 票数:1

我能想到的最好的方法是生成每对的和的矩阵,然后将这些行合并在一起,进行合并排序。 我觉得我错过了一些简单的见解,可以揭示更有效的解决方案。

我的算法,在Haskell中:

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 [] ',因为它更快。

===============>>#7 票数:1

无论你做什么,没有输入值的额外约束,你都不能比O(n ^ 2)做得更好,因为你必须迭代所有数字对。 迭代将主导排序(您可以在O(n log n)或更快)中进行排序。

===============>>#8 票数:-4

如果你正在寻找一个真正与语言无关的解决方案,那么你会对我的观点感到非常失望,因为你会遇到for循环和一些条件。 但是如果你把它打开到函数式语言或函数式语言特性(我正在看你LINQ)那么我的同事可以在这个页面中用Ruby,Lisp,Erlang和其他的优秀例子填充这个页面。

  ask by Peter Burns translate from so

未解决问题?本站智能推荐:

关注微信公众号