我正在参加一个关于麻省理工学院计划的编程课程的练习考试。其中一个问题是:
“完成程序(按顺序ls)返回列表ls,除了在严格大于的第一个值之前停止,而不是ls中的前一个值。换句话说,在-order应该从开始的开始返回按严格递增的顺序排序的部分。假设ls只包含非负整数。“
然后问题显示了几个例子:
(in-order '(1 2 3 4)) ; should return (1 2 3 4)
(in-order '(1 2 3 3 4 5)) ; should return (1 2 3)
(in-order '(3 2)) ; should return (3)
(in-order '(3)) ; should return (3)
这是我尝试解决方案:
(define (in-order ls)
(cond ((null? ls) ls)
((< (car ls) (cadr ls))
(cons (car ls) (cons (in-order (cdr ls)) ())))
((>= (car ls) (cadr ls)) (car ls))
(else "Nothing")))
接近使用第二和第三个例子,但是第一个和第四个例子彻底失败了。我知道它一直试图传递null作为参数的一部分,但我不确定如何解决这个问题。除此之外,还有什么我错了吗?
答案 0 :(得分:2)
这可以帮助你:
(define (in-order ls)
(if (null? ls)
'()
(let looking ((result (list (car ls))) (ls (cdr ls)))
(if (or (null? ls) (not (< (car result) (car ls))))
(reverse result)
(looking (cons (car ls) result)
(cdr ls))))))
尾递归looking
总是将最后一个值作为结果car
。因此,停止的比较变为(not (< (car result) (car ls)))
在您的代码中,(cons (in-order ...) ())
几乎肯定是错误的。谓词(< (car ls) (cadr ls))
会因'(3)
之类的内容而失败 - 您需要(null? (cdr ls))
这样的内容来避免这种情况。
在非尾递归算法中,与您的类似,它将是:
(define (in-order ls)
(cond ((or (null? ls) (null? (cdr ls))) ls) ; nothing left
((< (car ls) (cadr ls)) ; extend and continue
(cons (car ls) (in-order (cdr ls))))
(else (list (car ls))))) ; last one