group :: Num a => [a] -> [[a]]
group (a:b:t) = [a,b] : group t
group [a] = [[a]]
group [] = []
(%) :: (Num a, Eq a) => a -> a -> a
a % 1 = a
1 % b = b
a % b = a * b
prod_one_or_two :: (Num a, Eq a) => [a] -> a
prod_one_or_two [a, b] = a % b
prod_one_or_two [x] = x
insert_new_value :: (Num a, Eq a) => ([a], a) -> [a]
insert_new_value ([a, b], c) = [c % b, c % a]
insert_new_value ([x], c) = [c]
products_but_one :: (Num a, Eq a) => [a] -> [a]
products_but_one [a] = [1]
products_but_one l =
do combination <- combinations ; insert_new_value combination
where
pairs = group l
subresults = products_but_one $ map prod_one_or_two pairs
combinations = zip pairs subresults
在线尝试!
说我们得到了清单[a,b,c,d,e,f,g,h]
。我们首先将其成对分组[[a,b],[c,d],[e,f],[g,h]]
。然后,我们递归于pairs
他们产品的一半尺寸列表以获取subresults
[a*b, c*d, e*f, g*h] -> [(c*d)*(e*f)*(g*h), (a*b)*(e*f)*(g*h), (a*b)*(c*d)*(g*h), (a*b)*(c*d)*(e*f)]
如果我们采取的第一个元素(c*d)*(e*f)*(g*h)
,并用它乘b
与a
分别,我们得到了,但所有的产品a
和所有,但b
。对每个对执行此操作,并在缺少该对的情况下执行递归结果,我们得到最终结果。奇数长度的情况是通过将奇数元素不成对传递给递归步骤来专门处理的,返回的其余元素的乘积就是没有它的乘积。
乘法的数量t(n)
是n/2
用于配对产品,t(n/2)
为递归调用,另外n
的产品时,单个元素。这让人t(n) = 1.5 * n + t(n/2)
感到奇怪n
。使用更精确的计数奇数n
,并且忽略与相乘1
为基础案例给出得分2997
为n=1000
。