【问题标题】:Recursive sublist? function递归子列表?功能
【发布时间】:2015-02-28 13:16:02
【问题描述】:

我似乎不知道如何编写一个正确的 uscheme(MIT 方案的派生)函数,该函数将返回布尔值是否包含一个较小的列表。

这是我写的。

(define sublist? (xs ys)
    (if (= xs '())
        #t
        (if (= ys '())
            #f
            (if (= (car xs) (car ys))
                (sublist? (cdr xs) (cdr ys))
                (sublist? xs (cdr ys))
            )
        )
    )
)

它通过了我的大部分测试用例,除了这个测试用例。

(sublist? '(a b c) '(1 2 a 3 b 4 c 5 6))
;; this returns true while it's supposed to return false

测试用例要求子列表是连续的,中间没有随机元素。

我有点不知道如何纠正这个问题。还有其他人有想法吗?

【问题讨论】:

    标签: scheme


    【解决方案1】:

    问题在于您的算法过于急切——一旦找到两个相等的元素,它就会立即丢弃该元素并继续检查。实际上,找到两个相等的元素是不够的,因为如果您的算法找到不完整的匹配项,它可能不得不回溯。

    表示这种算法的最简单方法是使用辅助函数来确定子列表是否在列表中的给定位置匹配。然后sublist? 函数将遍历较大列表中的每个位置以查找匹配项。

    这是我的实现:

    (define (sublist? xs ys)
      (define (sublist-equal? xs ys)
        (cond
          ((null? xs) #t)
          ((null? ys) #f)
          ((equal? (car xs) (car ys))
           (sublist-equal? (cdr xs) (cdr ys)))
          (else #f)))
      (cond
        ((null? xs) #t)
        ((null? ys) #f)
        ((sublist-equal? xs ys) #t)
        (else (sublist? xs (cdr ys)))))
    

    注意内部的sublist-equal? 辅助函数。

    我还使用cond 代替嵌套的if 表达式,因为在这种情况下确实应该使用cond 来表示这种逻辑。此外,我使用equal? 而不是=,因为我所知道的大多数方案,= 用于数字比较(你的可能不同,我不知道)。

    【讨论】:

    • 是否可以在没有辅助函数的情况下做到这一点?
    • 这很好用。我希望有一个没有辅助功能的版本。感谢您的帮助!
    【解决方案2】:

    这是我的“没有辅助功能”的版本。不过,它确实使用了两个嵌套循环:

    (define (sublist? needle haystack)
      (if (null? needle)
          #t
          (let ((first (car needle)))
            (let outer ((cur haystack))
              (define (next)
                (outer (cdr cur)))
              (cond ((null? cur) #f)
                    ((eqv? (car cur) first)
                     (let inner ((lhs (cdr needle))
                                 (rhs (cdr cur)))
                       (cond ((null? lhs) #t)
                             ((null? rhs) (next))
                             ((eqv? (car lhs) (car rhs))
                              (inner (cdr lhs) (cdr rhs)))
                             (else (next)))))
                    (else (next)))))))
    

    【讨论】:

    • 不错的代码,但我的任务说它必须是递归的,而不是迭代的。
    • 从技术上讲,您的版本也是迭代的(Alexis 的版​​本也是如此)。 ;-) 但我会看看我能做些什么。
    【解决方案3】:
    (define sublist? (xs ys)
      (cond ((= xs '()) #t)  ;;cond easier to read than 
            ((= ys '()) #f)  ;;nested if statements
            ((and (= (car xs) (car ys)) 
     ;;need to check for more than singleton match
                  (or (null? (cdr xs))
                      (and (not (null? (cdr ys)))
                           (= (cadr xs) (cadr ys))
                           (sublist? (cdr xs) (cdr ys)))))) ;not tail call
      ;;this cond clause has no second part, 
      ;;the first will return #t or #f
      ;;will backtrack if #f is propagated up the stack.
             (else (sublist? xs (cdr ys)))) ; tail call
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-19
      • 1970-01-01
      • 2018-07-20
      • 2014-05-05
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 2013-11-10
      相关资源
      最近更新 更多