【问题标题】:How to find the uncommon items in a list (mutually exclusive)如何在列表中找到不常见的项目(互斥)
【发布时间】:2018-11-06 04:24:57
【问题描述】:

我的任务是编写一个方案函数,该函数可以生成一个新列表,其中包含仅存在于两个输入列表之一中的元素。 我设法创建了一个可行的解决方案:

(define remove
  (lambda (l item)
    (filter (lambda (x) (not (equal? x item))) l)))

(define uncommon_list
  (lambda (list1 list2)
    (cond 
      ((null? list2) list1)
      ((null? list1) list2)
      ((memv (car list1) list2)
       (uncommon_list (cdr list1) (remove list2 (car list1))))
      (else 
       (append (list (car list1)) (uncommon_list (cdr list1) list2))))))       

但是我觉得我把这个复杂化了,而且 O 复杂度不是很好?任何使这一点变得更好的指针都会很棒!谢谢

【问题讨论】:

  • ((memv (car list1) list2) (uncommon_list (cdr list1) (remove list2 (car list1)))) 也是错误的 - 考虑在 list1 中有重复的 (car list1)(假设 (remove xs x) 会从 xs 中删除所有出现的 x)。另外,你计算 A \ B,但symmetric difference 也应该包括 B \ A。
  • @WillNess 感谢您向我发送链接!实际上知道这个问题的正确术语非常有用,我想出了一个希望更好的解决方案,你能看看吗?

标签: list functional-programming set scheme boolean-operations


【解决方案1】:

对于最佳大 O,即 O(n),您需要创建集合,在 Scheme 中这意味着哈希表。解决方案是更新哈希,以便知道它是否在第一个、第二个或两个列表中找到。然后由不在两者中的元素组成一个列表:

#!r6rs

(import (rnrs base)
        (srfi :69))

(define (uncommon-elements l1 l2)
  (define hash (make-hash-table eqv?))
  (define (update-elements proc default lst)
    (for-each
     (lambda (e)
       (hash-table-update! hash e proc (lambda () default)))
     lst))

  (update-elements values 1 l1)
  (update-elements (lambda (e) (if (= e 2) 2 3)) 2 l2)
  (hash-table-fold hash
                   (lambda (k v acc)
                     (if (= v 3)
                         acc
                         (cons k acc)))
                   '()))

(uncommon-elements '(1 2 3 4 5) '(3 4 5 6 7 8))
; ==> (1 2 6 7 8)

(uncommon-elements '(1 1 2 2 3 3 4 5) '(3 4 5 6 7 8))
; ==> (1 2 6 7 8)

【讨论】:

  • 不幸的是,这比我迄今为止所学的更先进,但感谢您提供如此出色的答案!我会试着了解发生了什么
【解决方案2】:
(define a_minus_b(
        lambda (lista listb) (
            cond
                ((null? lista) `())
                ((memv (car lista) (cdr lista)) (a_minus_b (cdr lista) listb))
                ((memv (car lista) listb) (a_minus_b (cdr lista) listb))
                (else (cons (car lista) (a_minus_b (cdr lista) listb)))
        )
    )
)

(define symmetric_diff(
        lambda (list1 list2) (
            append (a_minus_b list1 list2) (a_minus_b list2 list1)
        )
    )
)

【讨论】:

  • 你肯定有一种不同寻常的括号风格。 :)
  • 为什么是“`()”?不应该是“'()”吗?它真的对你有用吗?如果是这样,在什么实施中?
  • @WillNess 来自 C,这对我来说是最容易阅读的,我正在使用 Racket v6.12 进行编译,` 一直对我有用,我从来不知道它应该是 '跨度>
  • 啊,我真傻。当然可以。反引号“`”是一个特殊的引号,它专门处理逗号“,”;没有逗号,它确实只是常规引用,“'”。
  • ' 是 quote 而 ` 是准引号。 ;-)
猜你喜欢
  • 2015-04-22
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2021-09-22
  • 2012-11-12
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多