簡體   English   中英

如何使簡單的Haskell函數遞歸?

[英]How can I make my simple Haskell function recursive?

這是我的功能:

rotatebyone :: [Int] -> [Int]
rotatebyone [] = []
rotatebyone (x:xs) = ((tail (x:xs)) ++ (take 1 (x:xs)))

rotatebyn :: Int -> [Int] -> [Int]
rotatebyn n [] = []
rotatebyn 1 (x:xs) = rotatebyone (x:xs) 
rotatebyn 2 (x:xs) = (rotatebyone (rotatebyone (x:xs)))

我希望我的功能重復n次。 我猜您是通過監護人或“ while”運算符來執行此操作的,但是我不知道該怎么做。 目標是將整數列表的元素旋轉n次。

這是我失敗的方法:

rota :: Int -> [Int] -> [Int]
rota n (x:xs) = rotatebyone (x:xs)
                where
                rota n
                    | n > 1 = rota (n - 1)
                    | otherwise = rotatebyone (x:xs)

您不應該通過旋轉一次並重復多次來旋轉多個位置。 讓我們看一下單次輪換的簡潔版本,了解原因:

rotateLeft1 :: [a] -> [a]
rotateLeft1 [] = []
rotateLeft1 (x:xs) = xs ++ [x]

問題在於, p ++ qp的長度上采用線性時間。 您為每個旋轉步驟執行一次此操作,這會浪費大量時間。 讓我們通過一個示例來不同地看待它。

rotateLeft 3 [1,2,3,4,5,6,7,8]
-- split the list
([1,2,3], [4,5,6,7,8])
-- swap the pieces
([4,5,6,7,8], [1,2,3])
-- Append
[4,5,6,7,8,1,2,3]

還剩下一個棘手的問題:如果我將列表旋轉大於其長度的數字怎么辦? 我讓你自己去做。

讓我們首先清理rotatebyone函數:

rotatebyone :: [Int] -> [Int]
rotatebyone [] = []
rotatebyone (x:xs) = ((tail (x:xs)) ++ (take 1 (x:xs)))

在這里,您將tail (x:xs)但這很奇怪,因為我們已經有了一條尾標: xs 因此我們可以將tail (x:xs)替換為xs

take 1 (x:xs) 這將以列表的開頭構造一個列表,因此[x] 因此,我們可以清理代碼以:

rotatebyone :: [Int] -> [Int]
rotatebyone [] = []
rotatebyone (x:xs) = xs ++ [x]

此外,您的函數僅適用於Int類型的列表(它具有簽名[Int] -> [Int] )。 但是,無論這些列表包含什么元素,我們都可以將列表旋轉一個,因此可以將其寫為:

rotatebyone :: [a] -> [a]
rotatebyone [] = []
rotatebyone (x:xs) = xs ++ [x]

現在,我們可以尋找一種旋轉n次的方法:

rotatebyn :: Int ->[a] -> [a]
rotatebyn ...

如果我們希望在零位上旋轉,則列表保持不變,因此作為基本案例,我們可以編寫:

rotatebyn 0 l = l

如果我們要旋轉一個或多個位置,可以通過rotatebyone函數旋轉一個位置,然后再將此結果旋轉n-1次:

rotatebyn n l = rotatebyn (n-1) (rotateone n)

或這些在一起:

rotatebyn :: Int ->[a] -> [a]
rotatebyn 0 l = l
rotatebyn n l = rotatebyn (n-1) (rotateone n)

但這就像@dfeuer所說的那樣效率不高:旋轉列表需要O(n)時間,如果我們需要進行k次操作,則時間復雜度為O(nk)

此外請注意,以上函數僅在n大於或等於零的情況下起作用。

暫無
暫無

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

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