【问题标题】:What is happening in each line of this code?这段代码的每一行发生了什么?
【发布时间】:2019-04-02 10:22:02
【问题描述】:

我知道整体代码是返回列表的最后第 n 个元素,但是,我不明白这个过程,比如在每一行中发生了什么(以及为什么,如果可能的话)?

(define (last-n lst n)
  (define (help-func lst drop)
    (cond
      ((> drop 0)
       (help-func (cdr lst ) (- drop 1)))
      (else
       (cdr lst ))))
  (if (= (length lst ) n )
      lst
      (help-func lst (- (length lst ) 1 n ))))

【问题讨论】:

    标签: scheme racket r5rs


    【解决方案1】:

    有一个小错误,当n 大于列表的长度时,您应该返回整个列表(或发出错误信号),我已修复它。下面是代码的分解:

    (define (last-n lst n)
      (define (help-func lst drop)
        (cond
          ; iterate while there are elements to drop
          ((> drop 0)
           ; advance on the list, and we're one
           ; element closer to reach our target
           (help-func (cdr lst) (- drop 1)))
          (else
           ; else we reached the point we wanted, stop
           (cdr lst))))
      ; if n is at least as big as the list
      (if (>= n (length lst))
          ; return the whole list
          lst
          ; else calculate how many elements
          ; we need to drop and start the loop
          (help-func lst (- (length lst) 1 n))))
    

    仅供参考,Racket 已经具有此功能,只需使用 take-right 内置程序,它甚至会更快,需要一次通过列表(您调用 length 几次,并且在一个不必要的聪明算法中)

    【讨论】:

    • 还不错。这是 O(n),你能做的最好的就是 O(n)。显而易见的事情是缓存length,但除此之外,与只执行一次的游标版本相比,您不会看到太多改进。
    • 当然,这一切都在相同的 O(n) 复杂度内。但是每次看到length 用于循环列表时我都会发痒,即使只有一次:P
    猜你喜欢
    • 2016-06-09
    • 2018-07-28
    • 1970-01-01
    • 2012-08-29
    • 2014-11-12
    • 2012-07-26
    • 2014-09-28
    • 1970-01-01
    相关资源
    最近更新 更多