可以通过弄乱给定索引中的字符串字符来解决这个问题。诀窍是string-ref
明智地使用。在这里,让我给您一些提示,指出适用于初学者语言的解决方案:
; this is the main procedure
(define (palindrome? s)
; it uses `loop` as a helper
(loop <???> <???> <???>))
; loop receives as parameters:
; `s` : the string
; `i` : the current index, starting at 0
; `n` : the string's length
(define (loop s i n)
(cond (<???> ; if `i` equals `n`
<???>) ; then `s` is a palindrome
(<???> ; if the char at the current index != its opposite (*)
<???>) ; then `s` is NOT a palindrome
(else ; otherwise
(loop <???> <???> <???>)))) ; advance the recursion over `i`
当然,有趣的部分是标有 的部分(*)
。0
想想看,如果索引处的字符等于索引处的字符n-1
(n
即字符串的长度)并且1
索引处的字符等于索引处的字符,则字符串是回文n-2
,依此类推。一般来说,如果索引处的字符确实i
等于索引处的字符n-i-1
(它的“相反”)对于 all i
,那么我们可以得出结论该字符串是回文 - 但如果一对相反的字符不等于彼此,那么这不是回文。
作为进一步的优化,请注意您不需要遍历整个字符串,只需测试字符串长度的一半(这在 Chris 的回答中对此进行了解释)就足够了 - 直观地,您可以看到,如果char ati
等于 char at n-i-1
,那么 char atn-i-1
等于 char at i
,所以不需要两次执行相同的测试。
尝试自己编写程序,不要忘记测试它们:
(palindrome? "")
=> #t
(palindrome? "x")
=> #t
(palindrome? "axa")
=> #t
(palindrome? "axxa")
=> #t
(palindrome? "axc")
=> #f
(palindrome? "axca")
=> #f
(palindrome? "acxa")
=> #f
(palindrome? "axcta")
=> #f