【问题标题】:How to write a function that utilizes a length function to recursively find and return a sub-list with the maximum length如何编写一个利用长度函数递归查找并返回具有最大长度的子列表的函数
【发布时间】:2019-10-17 16:53:05
【问题描述】:

我正在尝试回答这个编码问题,但我没有任何运气来解决这个问题。我不知道如何递归地找到子列表。

例如:(max_sub_list '(1 (1 2 3 4) (1 2 3))) => (1 2 3 4)

这是我的代码现在的样子,我需要一些帮助。

(defun max_sub_list (L)
  (if (>= (my-len (car L)) (my-len (cdr L)))
    (max_sub_list (cdr L))
    (return (my-len (L)))))

my-len 函数:

(if L
  (1+ (my-len (cdr L)))
  0)

使用我的原始代码,我遇到了问题CDR: 1 is not a list

我对 Lisp 很陌生,所以非常感谢任何帮助

更新:我决定使用两个函数来完成这个任务。这是我现在得到的:

(defun compare (a b)
    (cond
    ((> (my-len a) (my-len b))  a)
    (t b))
)
(defun max_sub_list (a)
    (compare(car(a) (max_sub_list(cdr(a)))))
)

更新 2:运行但不正确。

(defun compare (a b)
    (cond
    ((> (my-len a) (my-len b))  a)
    (t b))
)
(defun max_sub_list (a)

)
;;(write (compare '(1 2 3 4 5) '(1 2 3 4)))
(write (max_sub_list '(1 (1 2 3 4) (1 2 3))))

比较方法返回正确的值:(1 2 3 4 5) max_sub_list 方法现在返回 nil,因为其中没有任何内容。我需要使用列表中的car 与列表中的cdr 中的max_sub_list 来调用谓词(比较)。

【问题讨论】:

  • 1atom 而不是 list 所以没有 cdr。您需要检查给定列表的当前元素是否是一个列表。
  • (car (a)) 不可能是正确的,因为a 不是函数,请参阅 Rainer 的回答。
  • 那么如何比较列表的第一个值和 max_sub_list 中的列表的第二个值呢??
  • 我想我不明白你的意思。您能否以至少在没有语法错误的情况下运行的版本提供所有代码?据我所知,如果初始列表包含原子,您的代码仍然会失败。
  • 查看我实现的代码更新。我还添加了我需要的功能 max_sub_list 来做

标签: recursion common-lisp


【解决方案1】:
(defun max_sub_list (L)
  (if (>= (my-len (car L)) (my-len (cdr L)))
    (max_sub_list (cdr L))
    (return (my-len (L)))))

return 调用存在两个问题。

  1. Lisp 是一种面向表达式的语言。它返回表达式的值。只需要显式返回一个值,当我们想要从更早的部分计算或从某个特定调用中返回一个值时。

  2. return 在这里不起作用。 return 从名为 NIL 的块返回。您的代码中没有这样的块。但是有一个名为max_sub_list 的块,它是函数的名称,也是一个可以从中返回的块。因此,您可以从该块返回:(return-from max_sub_list (my-len (L)))。但正如我所说,在这种情况下你不需要它。 if 表达式返回 thenelse 值。

另一个问题是L 不是函数-> 它是变量。但是你的代码有(L),这是一个Lisp中的函数调用。

【讨论】:

    【解决方案2】:

    对于进一步的研究,没有任何保证,你可以从这个开始:

    (defun max-sub-list (list &optional (max-len 0))
      "Returns the length of the longest sublist of LIST."
      (let ((first-element (first list)))
        (cond ((null list) max-len)
              ((atom first-element) (max-sub-list (rest list) max-len))
              (t (when (> (length first-element) max-len)
                   (setf max-len (length first-element))
                   (max-sub-list (rest list) max-len))))))
    

    这将返回最大长度而不是最长的子列表。在比较子列表的长度以及是否需要其他测试用例时,您应该检查是否要使用>>=

    由于我的个人风格 YMMV,我使用 firstrest 而不是 carcdr

    【讨论】:

    • 使用此代码并在需要时插入 carcdr,我写了上面的列表并得到了 NIL,而不是 (1 2 3 4)
    【解决方案3】:

    尾调用递归解决方案:

    (defun max-sub-list (list &optional (acc '()) (max-len 0) (max-list '()))
      (cond ((null list) max-list)
            ((listp (car list)) (if (> (length (car list)) max-len)
                                    (max-sub-list (cdr list) acc (length (car list)) (car list))
                                    (max-sub-list (cdr list) acc max-len max-list)))
            (t (max-sub-list (cdr list) acc max-len max-list))))
    

    或:

    (defun max-sub-list (list &optional (acc '()) (max-len 0) (max-list '()))
      (cond ((null list) max-list)
            ((and (listp (car list))
                  (> (length (car list)) max-len))
             (max-sub-list (cdr list) acc (length (car list)) (car list)))
            (t (max-sub-list (cdr list) acc max-len max-list))))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 2017-06-23
      • 2021-11-20
      • 2022-11-23
      • 2018-02-19
      • 1970-01-01
      相关资源
      最近更新 更多