列表之间的两个常见元素

时间:2017-06-05 11:01:11

标签: lisp common-lisp

我对此功能two-similar-p有疑问。

(defun two-similar-p (list1 list2) 
  (mapcar 
   (lambda (e) 
     (mapcar 
      (lambda (e1)
        (if (equal e e1) t))
      list2))
   list1))

但是使用mapcar是不正确的,因为此函数返回一个包含TNIL的新列表,但我只需要返回true或false。

离。

(two-similar-p '(2 1 3) '(1 2 3))
==> ((NIL T NIL) (T NIL NIL) (NIL NIL T))

我正在考虑使用递归来比较各种元素,但我不知道如何做到这一点。 我的功能需要像:

(two-similar-p '(1 2 3) '(1 4 5)) ; ==> nil

(two-similar-p '(1 2 5) '(1 4 5)) ; ==> t

(two-similar-p '(1 2 6) '(6 4 2)) ; ==> t

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

最简单的“现成”解决方案是检查intersection是否包含至少两个元素:

(defun two-similar-p (l1 l2)
  (consp (cdr (intersection l1 l2 :test #'equal))))

稍微少一点的OTS解决方案是使用hash tables

(defun two-similar-p (l1 l2)
  (let ((h1 (make-hash-table :test 'equal))
        (common 0))
    (dolist (x l1)
      (setf (gethash x h1) t))
    (dolist (x l2)
      (when (gethash x h1)
        (incf common))
      (when (>= common 2)
        (return t)))))

第二种方法的优点是其复杂性为O(len(l1) + len(l2)), 而mapcar方法将为O(len(l1) * len(l2))

标准没有指定intersectionfriends的复杂性,但大多数实现都在这里照顾好用户(IOW,复杂性将是线性的,而不是二次的)。