codeingame.com で見つけたトレーニング演習を解こうとしています。
質問は次のとおりです。数値のリストがあり、とがリストの前にあるv_small - v_big
という条件で、の差の最小値を見つけたいとします。さらに、この質問の最大時間は 1 秒で、最大メモリ使用量は 512MB です。v_big > v_small
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
生成すると思います。最後のリストには 99999 個の要素があり、時間がかかります。n*(n+1)/2
n
次の試行は、局所的な最大値と最小値を見つけて、最大値と最小値のみを比較することでした。これにより、アルゴリズムのコストが #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)
では、このアルゴリズムを高速化する方法、またはより高速な別のアルゴリズムはありますか?