recursion - 有没有更有效的方法来编写这个递归过程?

标签 recursion functional-programming scheme tail-recursion pascals-triangle

我被要求编写一个程序,通过递归过程来计算帕斯卡三角形的元素。我可以创建一个过程,返回三角形中的单行或特定行中的数字。

这是我的解决方案:

(define (f n)
  (cond ((= n 1) '(1))
        (else
         (define (func i n l)
           (if (> i n)
               l
               (func (+ i 1) n (cons (+ (convert (find (- i 1) (f (- n 1))))
                                        (convert (find i (f (- n 1)))))
                                     l))))
         (func 1 n '()))))

(define (find n l)
  (define (find i n a)
    (if (or (null? a) (<= n 0))
        '()
        (if (>= i n)
            (car a)
            (find (+ i 1) n (cdr a)))))
  (find 1 n l))

(define (convert l)
  (if (null? l)
      0
      (+ l 0)))

这似乎工作正常,但查找以 (f 8) 开头的较大行的元素确实效率很低。有没有更好的程序通过递归过程来解决这个问题?

另外,如果我想使用迭代过程(尾递归),我该如何编写它?

最佳答案

优化算法的方法有多种,最好的方法之一是使用 dynamic programming有效地计算每个值。这是我自己的solution类似的问题,其中包括更好地理解这种方法的引用资料 - 这是一个尾递归的迭代过程。关键点是它使用变异操作来更新预先计算值的向量,并且调整实现以打印给定行的列表是一件简单的事情:

(define (f n)
  (let ([table (make-vector n 1)])
    (let outer ([i 1])
      (when (< i n)
        (let inner ([j 1] [previous 1])
          (when (< j i)
            (let ([current (vector-ref table j)])
              (vector-set! table j (+ current previous))
              (inner (add1 j) current))))
        (outer (add1 i))))
    (vector->list table)))

或者,借用 @Sylwester 的 solution我们可以编写一个纯函数式尾递归迭代版本,它使用列表来存储预先计算的值;在我的测试中,这比以前的版本慢:

(define (f n)
  (define (aux tr tc prev acc)
    (cond ((> tr n) '())          
          ((and (= tc 1) (= tr n))
           prev)
          ((= tc tr)
           (aux (add1 tr) 1 (cons 1 acc) '(1)))
          (else 
           (aux tr
                (add1 tc) 
                (cdr prev)
                (cons (+ (car prev) (cadr prev)) acc))))) 
  (if (= n 1)
      '(1)
      (aux 2 1 '(1 1) '(1))))

无论哪种方式,对于较大的输入,它都能按预期工作,对于 n 来说速度会很快。值约为几千个:

(f 10)
=> '(1 9 36 84 126 126 84 36 9 1)

关于recursion - 有没有更有效的方法来编写这个递归过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26103641/

相关文章:

JavaScript : Make an array of value pairs form an array of values

scheme - Typed Racket 中的绘图功能

java - 拼图碎片的排列

java - 如何递归地找到链表中倒数第二个出现的 Char ?

parsing - 为解析器/词法分析器规范提供类型系统?

javascript - Ramda帮助: Pointfree implementation w/placeholders to direct arguments

recursion - 初学者方案 : Procedures that return themselves

haskell - 表示 MIT 方案中未定义的结果

C# 匿名函数递归

javascript - 递归 JS 函数列出 Hx HTML 标签?