由@ Ed'ka提供的解决方案简洁而好看,但尽管如此,它的复杂性却是O(N)
。
我建议你考虑Exponentiation by squaring method,它提供了O(log(N))
复杂的功率计算。使用这种技术,笛卡尔功率可以用这种方式实现:
%% Entry point
cart(List, N) ->
Tmp = [[X] || X <- List],
cart(Tmp, Tmp, N).
cart(_InitialList, CurrList, 1) ->
CurrList;
cart(_InitialList, CurrList, N) when N rem 2 == 0 ->
Tmp = mul(CurrList, CurrList),
cart(Tmp, Tmp, N div 2);
cart(InitialList, CurrList, N) ->
Tmp = cart(InitialList, CurrList, N - 1),
mul(InitialList, Tmp).
mul(L1, L2) ->
[X++Y || X <- L1, Y <- L2].
P.S.从壳(我已经打包功能cart
成mudule my_module
)使用示例:
1> c(my_module).
{ok,my_module}
2>
2> my_module:cart([0,1], 2).
[[0,0],[0,1],[1,0],[1,1]]
3>
3> my_module:cart([0,1], 3).
[[0,0,0],
[0,0,1],
[0,1,0],
[0,1,1],
[1,0,0],
[1,0,1],
[1,1,0],
[1,1,1]]
MUL是缺少的部件。我无法得到它返回正确的结构,主要是因为我不明白,正确的输入不是([a,b],[a,b]),而是([[a],[b]] ,[[a],[b]]) – faibistes
函数mul计算两个列表的笛卡尔乘积。您可能会注意到那里使用的列表串联语法(运算符'++')。所以,这意味着 - 该功能仅适用于列表清单。这就是为什么你必须调用'mul([[a],[b]],[[a],[b]])'而不是'mul([a,b],[a,b])''。如果你看看入口点(函数'cart/2') - 你可能会注意到,我**将输入列表转换为列表列表**(通过将每个元素包装在自己的列表中:'[[X] || X < - List]',所以列表'[a,b]'转换为'[[a],[b]]')。 – stemm
如果'++'运算符是O(1),但不幸的是它是O(N)(其中N是左边参数的长度),那么它就是O(log(N)), |]'带''''''。你的解决方案确实比我的第一个版本运行得更快(恒定的差异),但我怀疑这是由于第二种情况下的尾部呼叫造成的。例如,如果我使我的解决方案为尾递归(请参阅我的更新),它会比您的更快(再次,不变)。 –