我坚持做作业问题,可以使用任何提示或建议。我需要使用Scheme在列表中找到 n 最大的数字。我试图通过创建主函数调用的辅助函数来做到这一点。到目前为止,我有这个:
(define (get_max_value L)
(if (null? L)
'()
(apply max L)
)
(define (biggest_nums L n)
(if (null? n)
'()
(cons (get_max_value L) (biggest_nums L (- n 1)))
)
)
当我在命令提示符下键入(largest_num'(3 1 4 2 5)3)时,drRacket只会挂起并且甚至不会返回错误消息。我哪里错了?
答案 0 :(得分:1)
只需对列表进行排序,然后返回第一个n
元素。
但是,如果列表很长且n
不是很大,那么您可能不想先对整个列表进行排序。在这种情况下,我会建议这样的事情:
(define insert-sorted
(lambda (item lst)
(cond ((null? lst)
(list item))
((<= item (car lst))
(cons item lst))
(else
(cons (car lst) (insert-sorted item (cdr lst)))))))
(define largest-n
(lambda (count lst)
(if (<= (length lst) count)
lst
(let loop ((todo (cdr lst))
(result (list (car lst))))
(if (null? todo)
result
(let* ((item (car todo))
(new-result
(if (< (car result) item)
(let ((new-result (insert-sorted item result)))
(if (< count (length new-result))
(cdr new-result)
new-result))
result)))
(loop (cdr todo)
new-result)))))))
答案 1 :(得分:1)
您的代码有两个主要问题:
L
始终保持不变。进行递归调用时,L的大小不会减小,因此每次递归调用的最大值始终都是相同的数字。n
以确保其中包含正确数量的数字。要以最微不足道的方式解决这两个问题,您可以在(< n 1)
中添加if
条件,并使用(cdr L)
之类的内容使L
减少每次递归调用的大小,每次都删除一个元素。
(define (biggest-nums n L)
(if (or (empty? L)
(< n 1))
'()
(cons (apply max L) (biggest-nums (- n 1) (cdr L)))))
所以当我们运行它时:
> (biggest-nums 3 '(1 59 2 10 33 4 5))
输出应该是什么?
'(59 33 10)
什么是实际输出?
'(59 59 33)
好的,所以我们让你的代码运行,但它仍然存在一些问题。你知道为什么发生了什么?你可以单步执行代码来弄清楚你可以做些什么来修复它吗?
答案 2 :(得分:1)
最简单的解决方案是首先按升序对数字进行排序,然后先取n
。这在Racket代码中非常简单地翻译:
(define (biggest_nums L n)
(take (sort L >) n))
按预期工作:
(biggest_nums '(3 1 4 2 5) 3)
=> '(5 4 3)