Haskell:蛮力和最大的子阵列问题

时间:2012-09-14 11:42:02

标签: algorithm haskell

我试图用强力方法解决maximum sub array problem,即产生所有可能的子阵列组合。我得到了一些有效的东西,但它根本不令人满意,因为它产生了太多重复的子阵列。

有没有人知道使用最少数量的重复元素生成所有子数组([[]]形式)的智能方法?

顺便说一句,我是Haskell的新手。这是我目前的解决方案:

import qualified Data.List as L

maximumSubList::[Integer]->[Integer]
maximumSubList x = head $ L.sortBy (\a b -> compare (sum b) (sum a)) $ L.nub $ slice x
     where 
        -- slice will return all the "sub lists"
        slice [] = []
        slice x = (slice $ tail x) ++ (sliceLeft x) ++ (sliceRight x)

        -- Create sub lists by removing "left" part
        -- ex [1,2,3] -> [[1,2,3],[2,3],[3]]
        sliceRight [] = []
        sliceRight x = x : (sliceRight $ tail x)

        -- Create sub lists by removing "right" part
        -- ex [1,2,3] -> [[1,2,3],[1,2],[1]]
        sliceLeft [] = []
        sliceLeft x = x : (sliceLeft $ init x)

2 个答案:

答案 0 :(得分:6)

在标准Data.List模块中,列表上有许多有用的功能。

import Data.List

slice :: [a] -> [[a]]
slice = filter (not . null) . concatMap tails . inits

答案 1 :(得分:3)

dave4420's answer是如何使用智能,简洁的Haskell做你想做的事情。我不是Haskell的专家,但我偶尔会玩它并找到解决这样一个问题的有趣分心,并尽情找出它的确切原因。希望以下解释会有所帮助:)

dave4420答案的关键属性(你的答案没有)是(startPos, endPos)对它生成的每个子阵列都是唯一的。现在,如果 他们的startPosendPos不同,请观察两个子阵列是不同的。将inits应用于原始数组会返回一个子数组列表,每个子数组都有唯一的startPos和相同的endPos(等于数组中的元素数)。将tails依次应用于每个子数组会产生另一个子数组列表 - 每个输入子数组输出一个子数组列表。请注意,tails 不会干扰输入子数组之间的区别,因为通过在单个输入子数组上调用tails输出的子数组都保留相同的startPos:即,如果您有两个具有不同startPos es的子数组,并将它们都放在tails中,则从第一个输入子数组生成的每个子数组将与第二个输入子数组生成的每个子数组不同

此外,通过在单个子阵列上调用tails生成的每个子阵列都是不同的,因为尽管它们都共享相同的startPos,但它们都具有不同的endPos es。因此(concatMap tails) . inits生成的所有子阵列都是不同的。仅需要注意的是,没有任何子阵列被遗漏:对于从位置i开始到结束位置j的任何子阵列,该子阵列必须显示为通过应用j-i+1生成的tails列表{1}} i+1生成的inits列表{1}}。总而言之,每个可能的子阵列只出现一次!