Algorithm haskell中3项实施的最高产品

Algorithm haskell中3项实施的最高产品,algorithm,haskell,math,functional-programming,greedy,Algorithm,Haskell,Math,Functional Programming,Greedy,我想用haskell实现3个问题中最高乘积的算法。以下是问题陈述: 给定一个整数数组,找到可以从中得到的最高乘积 三个整数 例如,给定[1,2,3,4],算法应返回24。给定[-10,-10,5,1,6],3的最高乘积为600=-10*-10*6 我的尝试(假设第一次尝试没有失败): 我用[3,5,1,2,4,10,0,4,8,11]测试了这个实现,但是返回值是550,应该是880正数 在寻找最高数字的意义上,你是在正确的轨道上。然而,问题是a、b和c并不总是有序的 事实上,比如说我们有数字[6

我想用haskell实现3个问题中最高乘积的算法。以下是问题陈述:

给定一个整数数组,找到可以从中得到的最高乘积 三个整数

例如,给定
[1,2,3,4]
,算法应返回
24
。给定
[-10,-10,5,1,6]
,3的最高乘积为
600=-10*-10*6

我的尝试(假设第一次尝试没有失败):

我用
[3,5,1,2,4,10,0,4,8,11]
测试了这个实现,但是返回值是
550
,应该是
880
正数 在寻找最高数字的意义上,你是在正确的轨道上。然而,问题是a、b和c并不总是有序的

事实上,比如说我们有数字
[6,2,4]
。然后,
(a,b,c)
将通过递归进行演变的方式是:

(0,0,0) -> (6,0,0) -> (2,6,0) -> (4,2,6)
但是现在
a=4
,这意味着如果我们现在遇到
3
,我们将不会替换该值,而我们可以这样做,因为我们可以删除
2


虽然有很多方法可以解决这个问题,但最好的方法可能是维持秩序:确保
a有更有效的解决方案,但我倾向于更直接的方法,如:

import Data.List (subsequences)
f :: (Num a, Ord a) => [a] -> a
f = maximum . map product . filter ((==3) . length) . subsequences
将函数算法视为集合上的转换序列比将命令式循环转换为递归函数更为惯用

注意:如果您使用的是非常长的列表,其中效率是一个问题,那么您可以先对列表进行排序,然后取最低的两个和最高的三个,算法仍然有效:

takeFirstLast xs = (take 2 sorted) ++ (drop (length sorted - 3) sorted)
  where sorted = sort xs

然而,我最初的方法非常快,可以容纳大约100个大小的列表,而且非常容易理解。我不相信为了速度而牺牲可读性,直到有人告诉我这是一个实际的要求。

提示:我们对产生最高产品的元素了解多少?你的
a',b',c'
逻辑看起来是错误的。假设
a=8、b=5、c=2和
x=7来了。在下一次迭代中,您是否得到
a'=8,b'=7,c'=5
?提示:尝试将所有变量一起定义为
where(a',b',c')=if(…)then(x,a,b)else if(…)then(a,x,b)else…
(您也可以为此使用防护)@WillemVanOnsem:它们是列表中的三个最大值还是最大值和两个最小负数?@chi我试图定义所有这些变量,但我遇到了编译错误,这让人非常困惑。但是想法是使用模式匹配在if-then-else表达式中返回结果,对吗?如果列表可能包含负数,那么
sol2
是否需要另外两个参数来跟踪最小数?@AriaPahlavan我认为如果允许负数,事情会变得更加复杂。有各种有趣的边缘情况——例如,可能只有负数,在这种情况下,你想要的是最大的,而不是最小的。您还应该仔细考虑何时包含0可能是正确答案。最简单的(虽然效率很低)是计算所有的乘积:
maxprod3xs=maximum[x*y*z|x:ys很有趣。这是正确的论点非常微妙。我非常喜欢它!您可能喜欢
其中a:b:c:=conjure(sort:[Down a]->[Down a])xs xs d:e:z=sort xs
(使用
scopedtypevalues
)或者类似于获得三个最大元素和两个最小元素的更漂亮的方法(仍然是线性时间)。完整的细节。我同意这是一个非常微妙的论点和解释。谢谢!我也喜欢python soln。我的Java实现有点冗长/嘈杂,这有点困扰我的测试!你能详细说明一下列表是如何被转换以获得更愉快的结果的吗?然而,这是相当可笑的低效。a lis长度为n的t有2^n的子序列。大约有一半的子序列的长度至少为n/2,所以我们说的是O(n*2^n)。Youch!将其与Willem Van Onsem的解进行比较,即O(n)。这不仅仅是“多少”效率更高。在这里使用
子序列真的没有办法不使用指数。我同意可读性非常重要,但O(n*2^n)非常有害;此外,Willem Van Onsem的更高效解决方案也非常可读,尽管该解决方案使用了更多的“功能性”。
Prelude> sol1 [1,2,3,4]
24
Prelude> sol1 [3, 5, 1, 2, 4, 10, 0, 4, 8, 11]
880
import Data.List(sort)

sol1 (xa:xb:xc:xs) = sol2' (a,b,c) xs
    where [a,b,c] = sort [xa,xb,xc]
sol1_all = sol2_all' (0,0,0) (0,0)

sol2_all' (a,b,c) (d,e) []     = -- ...
sol2_all' t@(a,b,c) u@(d,e) (x:xs) = sol2_all' f g xs
  where f | x >= c = (b,c,x)
          | x >= b = (b,x,c)
          | x > a = (x,b,c)
          | otherwise = t
        g | x <= d = (x,d)
          | x <= e = (d,x)
          | otherwise = u
sol2_all' (a,b,c) (d,e) [] = max (a*b*c) (c*d*e)
sol2_all' t@(a,b,c) u@(d,e) (x:xs) = sol2_all' f g xs
  where f | x >= c = (b,c,x)
          | x >= b = (b,x,c)
          | x > a = (x,b,c)
          | otherwise = t
        g | x <= d = (x,d)
          | x <= e = (d,x)
          | otherwise = u
import Data.List(sort)

sol1_all (xa:xb:xc:xs) = sol2_all' (a,b,c) (a,b) xs
    where [a,b,c] = sort [xa,xb,xc]

sol2_all' (a,b,c) (d,e) [] = max (a*b*c) (c*d*e)
sol2_all' t@(a,b,c) u@(d,e) (x:xs) = sol2_all' f g xs
  where f | x >= c = (b,c,x)
          | x >= b = (b,x,c)
          | x > a = (x,b,c)
          | otherwise = t
        g | x <= d = (x,d)
          | x <= e = (d,x)
          | otherwise = u
class Solution:
    def maximumProduct(self, nums):
        a,b,c = d,e,_ = sorted(nums[:3])
        for x in nums[3:]:
            if x >= c:
                a,b,c = b,c,x
            elif x >= b:
                a,b = b,x
            elif x >= a:
                a = x
            if x <= d:
                d,e = x,d
            elif x < e:
                e = x
        return max(a*b*c,c*d*e)
import Data.List (subsequences)
f :: (Num a, Ord a) => [a] -> a
f = maximum . map product . filter ((==3) . length) . subsequences
takeFirstLast xs = (take 2 sorted) ++ (drop (length sorted - 3) sorted)
  where sorted = sort xs