Math 在Erlang中查找子集,请帮助我优化解决方案
充分披露。这是一个面试/预选问题,我在面试中没有解决。为了我自己的利益,我决定在Erlang中实现它 以下是问题陈述: 必须找到数组的子集数,其中最大数是剩余数之和。例如,对于以下输入: 1,2,3,4,6 这些子集将是 1+2=3 1+3=4 2+4=6 1+2+3=6 以下是我的解决方案: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)。 未
%学分: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,[]}]