[英]Tail recursion calling tail recursion
我正在嘗試通過尾部遞歸來解決帕斯卡的三角形。 我知道要執行尾遞歸,函數調用語句應該是最后一條指令。 像這兒:
(defn pascal [line colum, acc]
(if (or (= line 0) (= line colum) (= colum 0))
(+ acc 1)
(recur (dec line) colum
(pascal (dec line) (dec colum), acc))))
我的問題是:由於我使用遞歸調用作為遞歸的參數,它仍然有效嗎?
因為我不能代替這個:
(recur (dec line) colum
(pascal (dec line) (dec colum), acc))))
對此:
(recur (dec line) colum
(recur (dec line) (dec colum), acc))))
最好的祝福
也許我的答案與遞歸無關,而且這個問題與@Sylwester的答案完全不同,但是顯示另一種解決此問題的方法仍然很有用。
假設Pascal三角形具有以下屬性:
這意味着,您可以通過線性算法求解時間軸為O(n ^ 3)的帕斯卡三角形的任何元素。 它可能比O(n ^ 2)和遞歸的遞歸版本還差勁,但是它不會破壞堆棧,它使用了組合函數,我認為更好,因為它更簡單,更安全。 所以,我們開始:
(defn naive-factorial[n]
(reduce *' (range 1 (inc n))))
(defn combinatoric-formula[line pos]
(if (<= pos line)
(/
(naive-factorial line)
(*' (naive-factorial pos)
(naive-factorial (- line pos))))))
如您所見,使用了naive-factorial
函數,該函數乘以n
,從而得出O(n ^ 3)。 它與您的函數相同,但是沒有任何遞歸。
對於帕斯卡三角形,還有許多方法可以用不同的方式解決它們。 如果您有很多時間,其中一些技巧非常棘手: rosettacode.org
同樣在您的版本中,您可以通過+
在clojure中使用int
數學,請在任何情況下都可以在+'
函數中使用in +'
,這會導致產生大量數字(假設這意味着加法會將您的值轉換為biginteger類型,這將非常大數)。
此外,我翻譯的@Sylwester介紹給CLOĴ茜方案版本:
(defn pascal [row col]
(let [aux
(fn aux [tr tc prev acc]
(cond (> tr row) (throw (.Exception "invalid input"))
(and (= col tc) (= row tr)) (+' (first prev) (second prev)); the next number is the answer
(= tc tr) (recur (+' tr 1) 1 (cons 1 acc) '(1)) ; new row
:else (recur tr ; new column
(+' tc 1)
(next prev)
(cons (+' (first prev) (second prev)) acc))))]
(if (or (zero? col) (= col row))
1
(aux 2 1 '(1 1) '(1)))))
也許可以改進,但可以說明問題。 它計算了從第三行到提供的輸入的前一個的整個三角形,然后得到了答案。 功能方法非常棒且純粹。
這個版本的性能比線性版本差很多。 因此得到:
(time (combinatoric-formula 1000 100))
"Elapsed time: 2.73794 msecs" for linear version
(time (pascal 1000 100))
"Elapsed time: 135.426888 msecs" for tail recursion version
但是它仍然更加干凈和涼爽;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.