删除列表的最后一个元素(方案)

12 scheme racket

所以我必须删除方案中列表的最后一个元素.

例如,假设我有一个列表(1 2 3 4).我需要回复:

(1 2 3)
Run Code Online (Sandbox Code Playgroud)

我的想法:

reverse(list)
car(list)
reverse(list)
Run Code Online (Sandbox Code Playgroud)

reverse方案(球拍)中有功能吗?

Joh*_*nts 21

你写道:"倒车,倒车".我相信你的意思是写"反向,反向,反向".这个解决方案没有错; 它与列表的大小呈线性关系,就像使用标准列表的任何解决方案一样.

作为代码:

;; all-but-last: return the list, not including the last element
;; list? -> list?
(define (all-but-last l) (reverse (cdr (reverse l))))
Run Code Online (Sandbox Code Playgroud)

如果列表的多次遍历或另一个列表副本的不必要构造困扰您,您当然可以通过直接编写事物来避免它.

鉴于你几乎解决了,我将假设这不是功课.

这是球拍的样子:

#lang racket

(require rackunit)

;; all-but-last : return the list, except for the last element
;; non-empty-list? -> list?
(define (all-but-last l)
  (cond [(empty? l) (error 'all-but-last "empty list")]
        [(empty? (rest l)) empty]
        [else (cons (first l) (all-but-last (rest l)))]))

(check-equal? (all-but-last '(3 4 5))
              '(3 4))
Run Code Online (Sandbox Code Playgroud)


Tim*_*Tim 8

有一个reverse,但使用它不会很有效.我建议使用以下递归函数.

(define (remove-last lst)
    (if (null? (cdr lst))
        '()
        (cons (car lst) (remove-last (cdr lst)))))

(remove-last '(1 2 3 4)) ; returns '(1 2 3)
Run Code Online (Sandbox Code Playgroud)

if检查它是否在列表的最后一个元素.

  • 只有你使用非常狭窄的"遍历"定义.由于您的函数不是尾递归的,因此从您的调用堆栈中获取可能被视为第二次遍历. (4认同)
  • 实际上,`reverse` 是 O(n),就像你的函数一样。两种方法都可以。 (2认同)
  • @Chris:它们确实具有相同的复杂性类,但是这个算法的速度应该仍然是原来的两倍,因为它只遍历列表一次. (2认同)

Chr*_*ung 6

SRFI 1(在Racket中激活使用(require srfi/1))具有以下drop-right功能:

 (drop-right '(1 2 3 4) 1)   ; => (1 2 3)
Run Code Online (Sandbox Code Playgroud)

  • 基于这个答案,我相信核心球拍现在已经有了这个,因此不再需要"需要". (2认同)

cor*_*iKa 2

我会执行一个递归函数,如果后面的元素不是最后一个元素,则该函数会沿着列表向下移动并附加该元素(使用cons),如果不是最后一个元素,则不附加任何内容。

我已经很多年没有做过计划了,所以这就是我能做的。

有人可以运行如何实现它(除非这是家庭作业,否则他们可能不应该!)

  • @glowcoder:不正确。_Prepending_ 到链表的时间复杂度为 O(1)。向链表追加的时间复杂度为 O(n)。(请记住,Scheme 列表是单链表,而不是双链表。) (4认同)
  • 哦,我明白你在说什么。您正在解释我对“append”一词的使用,意思是实际的“append”函数,而不是“append”的纯文本概念。在这种情况下,我承认附加函数将导致函数的顺序膨胀。:) (2认同)