簡體   English   中英

Haskell(相當長)回文檢查

[英]Haskell (formidably long) palindrome check

我正在努力解決臭名昭著的H-99問題,並且在解決#6問題 (找出列表是否是回文)。 我知道大多數解決方案在合理的簡短列表上都能很好地工作。 現在,我將如何編寫一個函數來測試長的列表是否是回文,例如,

let ll = [1..10000000] ++ [10000000, 10000000-1..1] ++ [7]

我(天真的)試圖這樣測試:

isPalindrome [] = True
isPalindrome [_] = True
isPalindrome [x,y] = x==y
isPalindrome (x:xs) = isPalindrome [x,last xs] && (isPalindrome $ init xs)

我假設如果isPalindrome [x,last xs]False ,則&&的昂貴右側將不會被評估。

我概述了上面的內容,結果如下:

Mon Jun 30 18:33 2014 Time and Allocation Profiling Report  (Final)

   h99 +RTS -p -RTS

total time  =        1.29 secs   (1292 ticks @ 1000 us, 1 processor)
total alloc = 2,720,050,200 bytes  (excludes profiling overheads)

COST CENTRE  MODULE  %time %alloc

main         Main     95.6  100.0
isPalindrome Main      4.4    0.0

                                                          individual     inherited
COST CENTRE     MODULE                  no.     entries  %time %alloc   %time %alloc

MAIN            MAIN                     43           0    0.0    0.0   100.0  100.0
 CAF            Main                     85           0    0.0    0.0   100.0  100.0
  main          Main                     86           1   95.6  100.0   100.0  100.0
   isPalindrome Main                     87           2    4.4    0.0     4.4    0.0
 CAF            GHC.Conc.Signal          84           0    0.0    0.0     0.0    0.0
 CAF            GHC.IO.Encoding          77           0    0.0    0.0     0.0    0.0
 CAF            GHC.IO.Encoding.Iconv    75           0    0.0    0.0     0.0    0.0
 CAF            GHC.IO.Handle.FD         68           0    0.0    0.0     0.0    0.0
 CAF            GHC.Show                 63           0    0.0    0.0     0.0    0.0

從中我推斷出問題出在last xs ,這可能需要計算整個xs 如果是這樣,是否有解決方法? 還是只是[a..b]實現是貪婪的?

謝謝。

如您所料, last xs是個問題-它會在列表的長度上花費線性時間,並迫使立即生成整個列表( [a..b]是惰性的,通常與Haskell列表一樣)。 因此,您的isPalindrome函數總共將是二次時間。

對於簡單的實現,我將以xs == reverse xs ,它具有正確的漸近行為(線性),但是常數系數相對較高,最終將在reverse獲取點的內存中擁有列表的兩個完整副本。到列表末尾並開始產生結果。

您可以通過查看length然后在中途分割列表,或者在單遍操作中做一些更巧妙的操作來對這種方法進行某種程度的改進。

但是,我認為為了獲得更好的性能,您需要切換數據結構-我將研究諸如Data.DequeData.Sequence類的東西。

我認為這是last xs ,您懷疑。 建議:在執行任何遞歸操作之前,請在中點處分割字符串*,然后反轉下半部分。 然后,您在每次遞歸時都比較兩個字符串的第一個字符。 *如果字符串長度不固定,則兩個字符串都應包含中間字符。

建議在此reddit線程上使用一系列有趣的回文功能:

幼稚

palindrome list = reverse list == list

無點

palindrome = liftM2 (==) reverse id

適用性

palindrome = (==) <$> reverse <*> id

莫納迪奇

palindrome = reverse >>= (==)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM