Math 在Erlang中查找子集,请帮助我优化解决方案

Math 在Erlang中查找子集,请帮助我优化解决方案,math,erlang,subset,Math,Erlang,Subset,充分披露。这是一个面试/预选问题,我在面试中没有解决。为了我自己的利益,我决定在Erlang中实现它 以下是问题陈述: 必须找到数组的子集数,其中最大数是剩余数之和。例如,对于以下输入: 1,2,3,4,6 这些子集将是 1+2=3 1+3=4 2+4=6 1+2+3=6 以下是我的解决方案: %学分:http://stackoverflow.com/questions/1459152/erlang-listsindex-of-function 索引(项目,列表)->索引(项目,列表,1)。 未

充分披露。这是一个面试/预选问题,我在面试中没有解决。为了我自己的利益,我决定在Erlang中实现它

以下是问题陈述: 必须找到数组的子集数,其中最大数是剩余数之和。例如,对于以下输入: 1,2,3,4,6

这些子集将是

1+2=3

1+3=4

2+4=6

1+2+3=6

以下是我的解决方案:
%学分:http://stackoverflow.com/questions/1459152/erlang-listsindex-of-function
索引(项目,列表)->索引(项目,列表,1)。
未找到(u,[],u)->的索引;
索引(项目[项目|),索引)->索引;
索引(项目,Tl,索引)->索引(项目,Tl,索引+1)。
%求和
findSums(左)->
置换=生成LCOMBOS(L),
列表:过滤器(fun(LL)->案例索引
未找到->错误;
_->对
结束
结束,排列)。
%生成大小为2..legnth(L)-1的所有组合
生成目标(L)->
NewL=L--[列表:最后一个(L)],
尺寸=列表:序号(2,长度(新)),
列表:flatmap(fun(X)->simplePermute(NewL,X)end,size)。
%从列表L生成大小为R的排列列表
当R==0->
[[]];
simplePermute(L,R)->

这里有一个更优雅的版本

在这个版本中,我假设只有正数,希望能加快速度。另外,我有点累,所以可能会有一些小的拼写错误,但基本上是正确的:)

get_tails([])->[];
获取详细信息([[u])->[];
获取_-tails([X:XS])->[X:XS],获取_-tails(XS)]。
求和([])->[];
获取_和([])->[];
获取求和([X:XS])->[get_sums\u worker(X,XS):获取求和(XS)]
当S<0->[]时,获取工人的总和;
当S==0->[[]]时,获取工作者的总和;
当S>0->
求和(S,XS)+[[X:L]| L
A=列表:反向(列表:排序(A0)),
B=获取尾部(A),
列表:平面图(有趣的获取和/1,B)。

我不确定这能加快多少速度,因为我怀疑背包问题会简化为这个问题。

这似乎是您的算法:

  • 生成所有组合(2^n)
  • 对每组组合求和(n)
  • 搜索每个总和的列表(n)
  • 这看起来像是
    n*2^n
    。我认为这是计算的最快速度,因为你必须尝试列表中每个数字的所有组合顺序。也许有人可以纠正我

    但是,您的空间效率似乎是
    2^n
    ,因为它存储了所有组合,这是不必要的

    这就是我的想法,它只会累积结果:

  • 对于每个项目,在列表的其余部分搜索其组合
  • 要查找组合,请从目标编号中减去列表的第一个编号,然后在列表的其余部分中搜索加起来等于差值的组合
  • 输出:

    5> subsets:find_subsets([6,4,3,2,1]).
    [{6,[[3,2,1],[4,2]]},{4,[[3,1]]},{3,[[2,1]]},{2,[]},{1,[]}]
    
    get_tails([]) -> [];
    get_tails([_]) -> [];
    get_tails([X:XS]) -> [[X:XS],get_tails(XS)].
    
    get_sums([]) -> [];
    get_sums([_]) -> [];
    get_sums([X:XS]) -> [get_sums_worker(X,XS):get_sums(XS)]
    
    get_sums_worker(S,_) when S < 0 -> [];
    get_sums_worker(S,_) when S == 0 -> [[]];
    get_sums_worker(S,[X:XS]) when S > 0 ->
        get_sums_worker(S, XS) ++ [[X:L] || L <- get_sums_worker(S - X, XS)].
    
    sums(A0) ->
        A = lists:reverse(lists:sort(A0)),
        B = get_tails(A),
        lists:flatmap(fun get_sums/1, B).    
    
    -module(subsets).
    
    -export([find_subsets/1]).
    
    
    find_subsets(NumList) ->
      ReverseSorted = lists:reverse(lists:sort(NumList)),
      find_each_subset(ReverseSorted, []).
    
    find_each_subset([], Subsets) ->
      Subsets;
    find_each_subset([First | ReverseSorted], Subsets) ->
      [ { First, recurse_find_subsets(First, ReverseSorted, [])} | find_each_subset(ReverseSorted, Subsets)].
    
    recurse_find_subsets(_Target, [], Sets) ->
      Sets;
    recurse_find_subsets(Target, [Target | _Numbers], []) ->
      [[Target]];
    recurse_find_subsets(Target, [First | Numbers], Sets) when Target - First > 0 ->
      Subsets = recurse_find_subsets(Target - First, Numbers, []),
      NewSets = lists:map(fun(Subset) -> [ First | Subset] end, Subsets),
      recurse_find_subsets(Target, Numbers, lists:append(NewSets, Sets));
    recurse_find_subsets(Target, [_First | Numbers], Sets) ->
      recurse_find_subsets(Target, Numbers, Sets).
    
    5> subsets:find_subsets([6,4,3,2,1]).
    [{6,[[3,2,1],[4,2]]},{4,[[3,1]]},{3,[[2,1]]},{2,[]},{1,[]}]