我想使用Scheme语言创建一个高效的特殊列表。 E.g:
功能名称:
make-list
参数:max
(make-list max) -> (1 2 3 4 5 6 7 ... max)
我可以使用递归方法完成此任务。
#lang racket
(define (make-list max)
(define lst '())
(define count 1)
(make-list-helper lst max count))
(define (make-list-helper lst max count)
(cond
[(> count max) lst]
[else
(set! lst (append lst (list count)))
(make-list-helper lst max (add1 count)]))
但是,这种方法可以被认为是低的。我不知道如何提高列表的效率。有人可以帮帮我吗?
答案 0 :(得分:2)
关键原则是避免Schlemiel the Painter's algorithm,而不是append
:随着列表变长,使用make-list-helper
会反复占用越来越多。前面的元素是O(1),而附加是O(列表的长度);因此,让最里面的(max)
返回单个列表cons
,并使用{{1}}在递归上添加元素。
(我更喜欢迭代解决方案,但我是一个普通的lisper,所以我最好避免坚持任何的方案)。
不包含任何代码,以免损害您学习的乐趣。
答案 1 :(得分:2)
(define (make-list max)
(let f ((i max)(a '()))
(if (zero? i)
a
(f (- i 1) (cons i a)))))
这似乎是迭代的一个简单练习。
以上内容非常简单,您将在Scheme中的每个位置使用它。
确保您了解整个代码段的工作原理。
答案 2 :(得分:1)
“效率”的另一个定义可能是:用最少量的代码编写程序。考虑到这一点,问题的最短解决方案是使用现有程序来解决问题;例如,如果max = 10
:
(define (make-list max-val)
(build-list max-val add1))
(make-list 10)
=> '(1 2 3 4 5 6 7 8 9 10)
以上内容使用了属于Racket的build-list程序:
按顺序将proc应用于
0
到(sub1 n)
的整数,创建n个元素的列表。如果lst是结果列表,则(list-ref lst i)
是(proc i)
生成的值。
另一个选项,也适用于Racket,将使用iterations and comprehensions:
(define (make-list max-val)
(for/list ([i (in-range 1 (add1 max-val))]) i))
(make-list 10)
=> '(1 2 3 4 5 6 7 8 9 10)
无论哪种方式,鉴于程序是语言核心库的一部分,您可以确定它们的性能非常好,除非分析器表明它们是瓶颈,否则无需担心。