【问题标题】:Need help finding second largest number in a list. Racket [closed]需要帮助查找列表中的第二大数字。球拍[关闭]
【发布时间】:2017-08-02 05:28:34
【问题描述】:

我一直在为这个问题苦苦挣扎。有人可以通过使用最简单的可能递归方式来解释程序背后的逻辑吗?

谢谢。

【问题讨论】:

  • 你应该解释你在哪里以及为什么你在挣扎,并展示你拥有的一些代码。 (而不仅仅是说“程序”)
  • 最简单的解决方案:对列表进行排序并获取第二个元素。如果元素不能保证是唯一的,则跳过初始重复项。

标签: recursion functional-programming lisp racket


【解决方案1】:

有 2 个变量(比如 x 和 y)

在数字列表中移动

在 x 中保持最大,在 y 中保持前一个最大值(前一个 x 值)

最后返回 y 值。

请记住将每个值与 x 和 y 的当前值进行比较。

我已经对其进行了测试,并且可以正常工作,但我确定您想自己编写代码。注意选择 x 和 y 的起始值。

编辑

参考 cmets 中的讨论(使用 -inf.0 作为初始值,如@naomik 的回答):

(define steps 0)

(define (gt x y)
  (set! steps (add1 steps))
  (> x y))

(define (lt x y)
  (set! steps (add1 steps))
  (< x y))

(define (2ndLargest L)
  (let loop ((x -inf.0)  ; largest
             (y -inf.0)  ; second largest
             (L L))
    (cond
      [(empty? L)
       (printf "steps=~a;~n" steps)
       y]
      [(or (= (first L) x)(= (first L) y))
       (loop x y (rest L))]
      [(gt (first L) x)
       (loop (first L) x (rest L))]
      [(gt (first L) y)
       (loop x (first L) (rest L))]
      [else
       (loop x y (rest L))]
      )))

(define (2ndLargest2 L)
  (let loop ((x -inf.0)  ; largest
             (y -inf.0)  ; second largest
             (L L))
    (cond
      [(empty? L)
       (printf "steps=~a;~n" steps)
       y]
      [(or (= (first L) x)(= (first L) y))
       (loop x y (rest L))]
      [(lt (first L) y)             ; FIRST CHECK IF LESS THAN Y; 
       (loop x y (rest L))]
      [(gt (first L) x)
       (loop (first L) x (rest L))]
      [(gt (first L) y)
       (loop x (first L) (rest L))]
      )))

(define L '(8 3 4 5 6 2 7 3 10 12 -1 11))
(2ndLargest L)
(2ndLargest2 L)

(set! L '(11 8 3 4 5 6 2 7 3 10 -1 12))
(2ndLargest L)
(2ndLargest2 L)

(set! L '(8 3 4 5 6 11 7 3 10 12 -1))
(2ndLargest L)
(2ndLargest2 L)

输出:

steps=21;
11
steps=48;
11
steps=70;
11
steps=88;
11
steps=107;
11
steps=131;
11

如果先检查当前是否小于 y,则步数更多。

【讨论】:

  • 你不需要同时比较xy,除非当前值大于y
  • 我想,这正是为什么需要同时使用 x 和 y 检查当前值的原因。假设 x=10、y=8 和 current=9,不能仅将 current 与 x 进行比较并丢弃它。 9 是迄今为止的第二大值。此示例的列表可以是 '(8 10 9 ...)。
  • 是的,但是在确定5 小于y 之后,您真的需要检查x 吗?我同意,如果您不知道哪个更大,则需要同时检查两者,但是当您这样做时,您可能会逃脱每个项目的比较。
  • 我明白了。好点子。
  • @Sylwester :请参阅上面我的答案中的代码。如果先检查小于y,则步骤更多。
【解决方案2】:

我使用 foldl 对此进行了尝试——它的工作方式类似于 mso 的答案,使用累加器 (cons x1 x2) 跟踪列表中的两个(不同的)最高数字,其中 x1 是最高的,@ 987654324@第二高

对于空列表的输入或单数字列表的输入,此答案将返回 -inf.0

#lang racket

(define (second-largest xs)
  (cdr (foldl (lambda (y acc)
           (let ((x1 (car acc))
                 (x2 (cdr acc)))
             (cond ((> y x1) (cons y x1))
                   ((= y x1) (cons y x2))
                   ((> y x2) (cons x1 y))
                   (else (cons x1 x2)))))
         (cons -inf.0 -inf.0)
         xs)))

(second-largest '(8 3 4 5 6 2 12 7 3 10 12 -1 11))
;; => 11

【讨论】:

  • 它应该是第二个“最大”而不是最小的。使用 -inf.0 是个好主意。
  • @rnso wups,我最初写答案是为了找到第二小的答案,但在我发布之前修复了它。我只是忘记改名字了^_^
猜你喜欢
  • 2013-09-27
  • 2020-09-04
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 1970-01-01
  • 1970-01-01
  • 2013-12-06
  • 1970-01-01
相关资源
最近更新 更多