复制长度函数的有效方法

时间:2017-02-01 00:43:35

标签: recursion scheme lisp racket

我正在使用car& amp ;;复制球拍的长度功能。 cdr比较两个列表的长度并返回两个中较短的一个。

简单的长度函数是:

(define length
 (lambda (list)
    (if (null? list)
        0
        (+ 1 (length (cdr list))))))

当用于比较两个列表时

(define short
  (lambda (list1 list2)
    (if (<= (length list1) (length list2))
        list1
        list2)))

> (short '(a b c) '(1 2 3 4 5 6 7))

将返回&#39;(a b c)。

然而,这种方法是无效的,特别是当一个列表比另一个列表长得多时,因为它会在返回较短的列表之前迭代两个列表。

我有一个更有效的方法如下。但是我想知道是否有更有效/替代的方法来获得更短的长度而不检查两个列表的结尾。也许通过递归方式与car / cdr同时遍历列表,直到较短的列表首先到达它的结尾。

(define shorter?
  (lambda (list1 list2)
    (and (not (null? list2))
         (or (null? list1)
             (shorter? (cdr list1) (cdr list2)))))) 

(define shorter
  (lambda (list1 list2)
    (if (shorter? list2 list1)
        list2
        list1)))

3 个答案:

答案 0 :(得分:2)

您的shorter?程序尽可能高效 - andor特殊表单都会短路,并且会在任何值时停止评估表达式的结果为true(适用于or特殊表单)或false(适用于and特殊表单)。因此,只要其中一个列表达到null,递归就会停止。您的shorter?实施与此相同且效率相同:

(define shorter?
  (lambda (list1 list2)
    (cond ((null? list2) #f)
          ((null? list1) #t)
          (else (shorter? (cdr list1) (cdr list2))))))

如果你想要一个更紧凑的解决方案,你可以将两个程序放在一个程序中,使用一个名为let(如另一个答案中所示)或内部帮助程序,两者都是等效的。我将演示后一种方法:

(define (shorter lst1 lst2)
  (define (shorter-list list1 list2)
    (cond ((null? list2) lst2)
          ((null? list1) lst1)
          (else (shorter-list (cdr list1) (cdr list2)))))
  (shorter-list lst1 lst2))

答案 1 :(得分:2)

名为let&#39;方法提供了易于理解的代码。评论提供了解释:

(define (shorter l1 l2)
  (let loop ((al l2)         ; start with both full lists
             (bl l2))
    (cond
      [(empty? al) l1]       ; if al finishes, return l1 and end; 
      [(empty? bl) l2]       ; if bl finishes, return l2 and end;
      [else
       (loop (cdr al) (cdr bl))] ; else loop again with cdr of lists;
    )))

当岸上人员名单完成时,此功能将结束,并且不会不必要地持续到更长的列表结束。

答案 2 :(得分:-1)

我建议这样开始:

(define (shorter list-1 list-2) (shorter-loop list-1 list-2 list-1 list-2))

然后

(define (shorter-loop list-1 list-2 result-1 result-2)
  ;;
  )

辅助函数short-loop同时向下递归list-1和list-2。如果list-1变为null,则返回result-1,如果list-2返回null,则返回result-2。