-1

这是我到目前为止所做的:

(define sumOdd
    (lambda(n)
        (cond((> n 0)1)
             ((odd? n) (* (sumOdd n (-(* 2 n) 1)

输出看起来像这样:

 (sumOdd 1)  ==> 1
 (sumOdd 4)  ==> 1 + 3 + 5 + 7 ==> 16
 (sumOdd 5)  ==> 1 + 3 + 5 + 7 + 9 ==> 25 

这就是我想要做的:找到前 N 个奇数正整数的总和

我想不出只添加奇数的方法。

4

5 回答 5

1

让我们考虑几个案例:

1) (sumOdd 5) 应该返回什么?嗯,它应该返回 5 + 3 + 1 = 9。 2) (sumOdd 6) 应该返回什么?好吧,这也返回 5 + 3 + 1 = 9。

现在,我们可以通过多种方式编写此算法,但这是我决定考虑的一种方式:

我们将编写一个递归函数,从 n 开始,倒计时。如果 n 是奇数,我们想将 n 添加到我们的运行总数中,然后倒数2。为什么我要倒数2?因为如果 n 是奇数,则 n - 2 也是奇数。否则,如果 n 是偶数,我不想添加任何内容。但是,我想确保我继续递归,以便得到一个奇数。如何从偶数倒数到下一个奇数?我减去 1。我这样做,倒计时直到 n <= 0。我不想在我的运行总数中添加任何东西,所以我返回 0。这是该算法的样子:

(define sumOdd
  (lambda (n)
    (cond ((<= n 0) 0)
          ((odd? n) (+ n (sumOdd (- n 2))))
          (else (sumOdd (- n 1))))))

如果它对您有帮助,这里有一个稍微不同的算法的更明确的例子:

(define sumOdd
  (lambda (n)
    (cond ((<= n 0) 0)
          ((odd? n) (+ n (sumOdd (- n 1))))
          ((even? n) (+ 0 (sumOdd (- n 1))))))) ; note that (even? n) can be replaced by `else' (if its not odd, it is even), and that (+ 0 ..) can also be left out

编辑:

我看到问题已经改变了一点。要将前 N 个正奇数相加,有几个选项。

第一个选项:数学!

(define sumOdd (lambda (n) (* n n)))

第二种选择:递归。有很多方法可以做到这一点。例如,您可以生成 2*n 的列表并使用上述过程。

于 2013-03-01T00:58:42.207 回答
1

为了进一步阐述这个sum-odds问题,你可以用更抽象的过程来解决它,这些过程结合起来会积累所需的答案。这不一定是最简单的解决方案,但它很有趣,并且捕获了处理列表结构时常见的一些更通用的模式:

; the list of integers from n to m
(define (make-numbers n m)
  (if (= n m) (list n)                             ; the sequence m..m is (m)
      (cons n                                      ; accumulate n to 
            (make-numbers (+ n 1) m))))            ; the sequence n+1..m

; the list of items satisfying predicate
(define (filter pred lst)
  (if (null? lst) '()                              ; nothing filtered is nothing
      (if (pred (car lst))                         ; (car lst) is satisfactory
          (cons (car lst)                          ; accumulate item (car lst)
                (filter pred (cdr lst)))           ; to the filtering of rest
          (filter pred (cdr lst)))))               ; skip item (car lst)

; the result of combining list items with procedure
(define (build-value proc base lst)
  (if (null? lst) base                             ; building nothing is the base
      (proc (car lst)                              ; apply procedure to (car lst)
            (build-value proc base (cdr lst)))))   ; and to the building of rest

; the sum of n first odds
(define (sum-odds n)
  (if (negative? n) #f                             ; negatives aren't defined
      (build-value +                               ; build values with +
                   0                               ; build with 0 in base case
                   (filter odd?                    ; filter out even numbers
                           (make-numbers 1 n)))))  ; make numbers 1..n

希望这个答案很有趣,而且不会太混乱。

于 2013-03-01T02:47:24.773 回答
0

这是一个很好的尾递归实现:

 (define (sumOdd n)
  (let summing ((total 0) (count 0) (next 1))
    (cond ((= count n) total)
          ((odd? next) (summing (+ total next)
                                (+ count 1)
                                (+ next  1)))
          (else (summing total count (+ next 1))))))
于 2013-03-01T18:09:52.303 回答
0

更短的尾递归版本:

(define (sumOdd n)
  (let loop ((sum 0) (n n) (val 1))
    (if (= n 0)
        sum
        (loop (+ sum val) (- n 1) (+ val 2)))))
于 2013-03-01T19:17:28.637 回答
0

您需要有 2 个变量,一个用于记录仍要添加多少奇数的计数器,另一个用于保存当前奇数,该奇数在使用后增加 2:

(define (sum-odd n)
  (define (proc current start)
    (if (= current 0) 
        0
        (+ start (proc (- current 1) (+ start 2)) )))
    (proc n 1))
于 2013-03-01T15:55:58.013 回答