LISP检查列表是否对称而没有反向

时间:2009-09-15 11:46:14

标签: lisp

任何人都有关于如何做到这一点的任何想法...反向太慢,我想避免使用该功能。

基本上我希望能够在'(a b b a)出现或'(a b c d c b a)之类的情况下返回true

和false表示不对称的东西

5 个答案:

答案 0 :(得分:6)

我不确定为什么使用REVERSE效率不高;你有没有找到解决方案?您只需遍历列表一次即可完成;与(比如)查找列表的长度相同,然后您可以遍历两个列表进行比较。

如果你想成为一个小小的鸽友,你可以同时找到列表的长度并使用LOOP来反转它:

(defun fancier-palindrome-p (list)
  (let ((reversed '()) (length 0)) 
    (dolist (elt list)
      (incf length)
      (push elt reversed)) 
    (dotimes (i (floor length 2) t)
      (unless (eql (pop list) (pop reversed))
        (return nil))))) 

这可以让你跳过一半的支票。我认为这不值得额外的复杂性。您还可以使用乌龟和兔子在列表中向下移动以节省一半的费用,但代价是更加复杂。

 (defun ridiculous-palindrome-p (list)
   (let ((reversed-front '()))
     (loop  
       :for tortoise :on list 
       :for hare :on list :by #'cddr 
       :until (null (cdr hare)) 
         :do (push (car tortoise) reversed-front)
       :finally  
         (return  
          (if (null hare) ; length is even 
            (equal tortoise reversed-front)
            (equal (cdr tortoise)  
                   reversed-front)))))) 

这些解决方案都没有比

更引人注目
(defun palindrome-p (list) (equal list (reverse list))

如果这确实是一个瓶颈,也许您最好使用向量作为序列表示来利用快速随机访问,如下所示:

(defun vector-palindrome-p (vector)
  (let* ((n (length vector)) (j n))
    (dotimes (i (floor n 2) (return t))
      (unless (eql (aref vector i) 
                   (aref vector (decf j)))
      (return nil)))))

答案 1 :(得分:1)

this不是一个好的解决方案吗?或者,您可以使用“palindrome lisp”作为您最喜爱的搜索引擎中的关键字来搜索其他解决方案。

答案 2 :(得分:0)

此功能避免使用反向:

(defun palindromp (a)
   (or (null a)
       (null (cdr a))
       (and (equal (car a) (car (last a)))
            (palindromp (butlast (cdr a))))))

答案 3 :(得分:0)

这是CommonLisp:

(defun pali (l)
  (labels ((scan (v n l)
             (or (>= n (/ l 2))
                 (and (equal (elt v n) (elt v (- l n 1)))
                      (scan v (+ n 1) l)))))
    (scan (apply #'vector l) 0 (length l))))

您之前使用过“labels”吗?你去(在Scheme中):

(define (palindrome? l)
  (let scanning ((v (list->vector l)) (n 0) (len (length l)))
    (or (>= n (/ len 2))
        (and (equal? (vector-ref v n) (vector-ref v (- len n 1)))
             (scanning v (+ n 1) len)))))

答案 4 :(得分:-1)

(defun   pal()

(format t "enter list")

(setf list1(read))

(print list1)

(setf list2(rev list1))

(if (equal list1 list2)

(print "palindrome")

(print "not palindrome")))


(reverse (list1)

(setf list2 nil)

(do ((i 1 (+ i 1)))((equal list1 nil)

(format t "reverse list")

(print list2))

(setf list2 (cons (car list1) list2))

(setf list1 ( cdr list1))))