检查列表的反向是否与列表相同?

时间:2012-09-30 00:01:30

标签: recursion scheme racket reverse

我正在学习方案,我要做的一件事就是递归,以确定列表是否具有反射性,即列表在反转时看起来是一样的。我必须原始这样做,所以我不能使用反向方法列表。我还必须使用明显的递归。问题是在方案中,使用我们学到的非常基本的东西很难访问列表或缩短列表,因为它们有点像链接列表。我也想不使用索引。 有了这个说我有一些想法,并想知道如果这些充足,你认为我可以用方案的基础知识做得更好。

  1. 使用递归(我的实现)反转列表并比较原始版本和此版本。列表。
  2. 通过递归列表的其余部分来比较第一个和最后一个元素,以找到最后一个元素并与第一个元素进行比较。跟踪我已经递归的次数,然后为列表的倒数第二个元素少做一次,以与列表的第二个元素进行比较。 (这是非常复杂的事情,因为我已经尝试过它并且失败了,但我想看到你们会做同样的事情)
  3. 缩短列表以每次修剪第一个和最后一个元素并进行比较。我不确定是否可以使用方案的基础来完成。
  4. 您的建议或提示或任何内容。我很擅长计划。谢谢阅读。我知道这很长。

3 个答案:

答案 0 :(得分:3)

检查列表是否为回文而不反转"There and Back Again" by Danvy and Goldberg中解释的技术示例之一。他们在(ceil (/ (length lst) 2))递归调用中执行此操作,但有一个更简单的版本可以在(length lst)调用中执行此操作。

以下是解决方案的框架:

(define (pal? orig-lst)
  ;; pal* : list -> list/#f
  ;; If lst contains the first N elements of orig-lst in reverse order,
  ;; where N = (length lst), returns the Nth tail of orig-lst.
  ;; Otherwise, returns #f to indicate orig-lst cannot be a palindrome.
  (define (pal* lst)
    ....)

  .... (pal* orig-lst) ....)

这听起来像是家庭作业,所以我不想填写所有的空白。

答案 1 :(得分:2)

我同意#1似乎是去这里的方式。它很简单,我无法想象它失败了。也许我没有足够强大的想象力。 :)

您正在考虑的其他选项看起来很尴尬,因为我们讨论的是链接列表,它直接支持顺序访问,但不支持随机访问。如您所知,“索引”到链接列表是禁止的。它最终在列表结构中尽职尽责地进行游行。因此,其他选择肯定是可行的,但它们很昂贵。

这笔费用不是因为我们在Scheme中:这是因为我们正在处理链接列表。只是为了确保它是清楚的:Scheme具有支持快速随机访问的向量(数组)。在矢量上测试回文就像你期望的那样容易:

#lang racket
;; In Professional-level Racket

(define (palindrome? vec)
  (for/and ([i (in-range 0 (vector-length vec))]
            [j (in-range (sub1 (vector-length vec)) -1 -1)])
    (equal? (vector-ref vec i)
            (vector-ref vec j))))

;; Examples
(palindrome? (vector "b" "a" "n" "a" "n" "a"))
(palindrome? (vector "a" "b" "b" "a"))

因此,我认为,你要解决的问题的一个方面是表明你选择的数据结构 - 问题的表示 - 可以对问题解决方案产生强烈影响。

(旁白:#2肯定是可行的,但它违背了单链表数据结构的细节。#3的方法要求对表示进行彻底改变:从第一眼看,我认为你是需要可变的,双链表来解决任何正义,因为你需要能够向后行进

答案 2 :(得分:0)

要回答dyoo的问题,你不必知道你处于中间位置;你只需要进行一定的比较。如果这种比较有效,那么a)字符串必须是可逆的,b)你必须处于中间点。

如果能够达到目的,那么就会有更有效的解决方案......