You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

计算回文数遇无限循环,求基于SICP第1章的Racket解法(欧拉计划4题)

用SICP风格的递归解决Project Euler第4题(避免无限循环)

嘿,太懂你现在的处境了——刚啃SICP第一章,满脑子递归,碰Project Euler的题却看到一堆循环解法,还踩了无限循环的坑!我当初学SICP的时候也干过这事,给你分享个纯递归的思路,完全符合第一章的知识范围,还能解决无限循环的问题。

首先,先明确核心问题:我们要找两个三位数乘积里最大的回文数,关键是用递归替代循环,同时给每一步递归设置明确的终止条件——这正是你之前无限循环的根源:没有收敛的边界。

第一步:写一个判断回文数的辅助函数

用Racket的字符串处理很方便,把数字转成字符串,再和反转后的字符串对比就行:

(define (palindrome? n)
  (let ((s (number->string n)))
    (equal? s (list->string (reverse (string->list s))))))

(注:Racket里reverse是处理列表的,所以要把字符串转成列表反转后再转回字符串)

第二步:递归遍历所有三位数对,记录最大回文数

我们从最大的三位数999开始往下遍历,对于每个数i,再从i开始往下遍历j(避免重复计算i*j和j*i),一旦i*j比当前找到的最大回文数小,就直接停止这个i的遍历——因为再往下j更小,乘积只会更小,没必要继续。

这里分两个递归函数:

  1. max-palindrome:负责遍历每个i从999到100
  2. check-pair:负责遍历每个j从i到100,检查乘积是否为回文
(define (max-palindrome start end current-max)
  (cond
    ((< start end) current-max)  ; 终止条件:start小于最小三位数,返回当前最大值
    (else
     ; 检查当前start和所有<=它的三位数的乘积,更新最大值
     (let ((new-max (check-pair start start current-max)))
       (max-palindrome (- start 1) end new-max)))))

(define (check-pair i j current-max)
  (let ((product (* i j)))
    (cond
      ((< product current-max) current-max)  ; 终止条件:乘积比当前最大值小,不用继续找j了
      ((palindrome? product) (max product current-max))  ; 是回文数,更新最大值
      (else (check-pair i (- j 1) current-max)))))  ; 不是回文数,j减1继续检查

第三步:调用函数得到结果

直接调用(max-palindrome 999 100 0),就能得到两个三位数乘积的最大回文数:906609(验证一下:993 × 913 = 906609)

为什么不会无限循环?

每个递归都有明确的终止条件:

  • max-palindrome里,start从999每次减1,直到小于100就停止
  • check-pair里,要么j减到小于100,要么乘积比当前最大值小就停止,不会一直递归下去

这个思路完全贴合SICP第一章的递归思想,没有用任何循环,还能高效地找到结果。

内容的提问来源于stack exchange,提问作者Patrick Olila

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:53:41