如何使用Scheme获取列表中最大的n个元素?

时间:2016-05-04 09:21:23

标签: scheme racket

我坚持做作业问题,可以使用任何提示或建议。我需要使用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只会挂起并且甚至不会返回错误消息。我哪里错了?

3 个答案:

答案 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)

您的代码有两个主要问题:

  1. L始终保持不变。进行递归调用时,L的大小不会减小,因此每次递归调用的最大值始终都是相同的数字。
  2. 在回复答案之前,您无法检查n以确保其中包含正确数量的数字。
  3. 要以最微不足道的方式解决这两个问题,您可以在(< 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)