我正在尝试解决我在 codeingame.com 上找到的训练练习
问题如下:您有一个数字列表,并希望找到 之间的差异的最小值v_small - v_big
,条件是和v_big > v_small
在列表中。另外这道题的最大时间是1秒,最大内存使用量是512MB。v_big
v_small
对于小型列表,一个简单的算法就足够了:
---------------------------------- try1.hs -------------------------------------
import Control.Applicative ((<$>))
main :: IO ()
main = do _ <- getLine
v <- g . f . map read . take 1000 . words <$> getLine --or equivalently
-- v <- g . h . map read . take 1000 . words <$> getLine
print v
f :: [Int] -> [Int]
f [] = []
f xx@(x:xs) = (minimum $ map (\y -> y-x) xx) : (f xs)
g :: [Int] -> Int
g [] = 0
g xs = minimum xs
h :: [Int] -> [Int]
h [] = []
h (x:xs) = (foldr (\y' y -> min (y'-x) y) 0 xs): (h xs)
但我认为这两个功能f
并h
生成n*(n+1)/2
许多元素,其中n
列表的长度。最后一个列表需要很长时间,有 99999 个元素。
下一次尝试是找到局部最大值和最小值,并仅将最大值与最小值进行比较 - 这应该会将算法的成本降低到 #maxima*#minima
---------------------------------- try2.hs -------------------------------------
import Control.Applicative ((<$>))
-- import Control.Arrow ((&&&))
data Extremum = Max Int | Min Int deriving (Show)
main :: IO ()
main = do _ <- getLine
e <- getExtremes
print e
getExtremes :: IO Int
getExtremes = minimum . concat . myMap f . headextr .
map read . take 1000 .words <$> getLine
myMap :: (a -> [a] -> [b]) -> [a] -> [[b]]
myMap _ [] = []
myMap g xx@(x:xs) = (g x) xx : myMap g xs
f :: Extremum -> [Extremum] -> [Int]
f (Max y) (Max _:xs) = f (Max y) xs
f (Max y) (Min x:xs) = (min 0 (x-y)): f (Max y) xs
f _ _ = []
headextr :: [Int] -> [Extremum]
headextr xx@(x:y:_) | x > y = Max x : extremes xx
| x < y = Min x : extremes xx
headextr xx = extremes xx
extremes :: [Int] -> [Extremum]
extremes [] = []
extremes [x] = [Max x, Min x]
extremes [x,y] | x > y = Min y:[]
| otherwise = Max y:[]
extremes (x:y:z:xs) | x > y && y < z = Min y:extremes (y:z:xs)
| x < y && y > z = Max y:extremes (y:z:xs)
| otherwise = extremes (y:z:xs)
但仍然没有达到所需的 1 秒时间。我减少了take 1000
用于分析的输入,但由于我不是专业程序员,我无法使用它,我发现的唯一信息 - 这很明显 - 在第一个版本f/h
中是昂贵的功能,而在第二个版本中版本f
也是罪魁祸首。
此练习的输入文件可在http://www.codingame.com/ide/fileservlet?id=372552140039找到- (如果此链接不起作用,可以在 www.codingame.com -> training -> 找到证券交易所损失 -> Test_5_input.txt/Test_5_output.txt)
那么如何加速这个算法,或者还有其他更快的算法吗?