P19 (**) Rotate a list N places to the left.

问题描述

sash> (rotate '(a b c d e f g h) 3)
   -> ((a b c) (d e f g h i k))
sash> (rotate '(a b c d e f g h) -2)
   -> (g h a b c d e f)

Hint: Use the predefined functions length and append, as well as the result of problem P17.

解法

  • 普通实现

    按照题目的提示,很直观得到:

    (define rotate
      (lambda (ls N)
        (cond
          [(zero? N) ls]
          [else
           (let* ([n (if (positive? N) N (+ (length ls) N))] [s (split ls n)]) (append (cadr s) (car s)))])))

    使用到了lengthappend,以及P17定义的split

  • CPS实现
    (define split-2
      (lambda (ls n k)
        (let f ([i 1]
                [s ls]
                [k k])
          (cond
            [(null? s) (k '() '())]
            [(<= i n) (f (+ i 1) (cdr s) (lambda (ls1 ls2) (k (cons (car s) ls1) ls2)))]
            [else (f (+ i 1) (cdr s) (lambda (ls1 ls2) (k ls1 (cons (car s) ls2))))]))))
    (define return
      (lambda (ls1 ls2)
        (append ls2 ls1)))
    
    (define rotate
      (lambda (ls N)
        (cond
          [(zero? N) ls]
          [else
           (let ([n (if (positive? N) N (+ (length ls) N))]) (split-2 ls n return))])))

    split-2的功能仍然是分割的两个列表,这个定义没有改变。这里改变了return的定义,用来组装split-2得到的两个列表,P17要求返回这两个列表作为元素的列表,而该题目则要求按规则append成一个列表。rotate则包含了顶层逻辑,处理N的各种情况对应的结果逻辑。

  • 其他方式

    看到另外一种解法:

(define (rotate xs n) 
  (if (< n 0) 
      (reverse (rotate (reverse xs) (- n))) 
      (let ((parts (split xs n))) 
        (append (cadr parts) (car parts))))) 

看似简洁,但有逻辑冗余:当n为负时,会用-n作为rotate的参数,这时仍然要判断if语句,实际上我们已经知道了-n为正。
不建议将对n的处理放入递归逻辑中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值