LISP检查列表是否对称而没有反转
任何人对如何做到这一点有任何想法。。。反转太慢,我想避免使用该函数 基本上,我希望在出现诸如“(abba)或“(abcdcba)之类的内容时能够返回trueLISP检查列表是否对称而没有反转,lisp,Lisp,任何人对如何做到这一点有任何想法。。。反转太慢,我想避免使用该函数 基本上,我希望在出现诸如“(abba)或“(abcdcba)之类的内容时能够返回true 对于非对称的事物,如果为false,这不是一个好的解决方案吗?或者你也可以在你最喜欢的搜索引擎中使用“回文lisp”作为关键词来搜索其他解决方案。我不确定为什么使用反向效率不够;你真的分析过这个解决方案吗?只需遍历列表一次即可;与查找列表的长度相同,然后可以遍历两个列表进行比较 如果您想成为一个小爱好者,您可以同时找到列表的长度,并使用循环
对于非对称的事物,如果为false,这不是一个好的解决方案吗?或者你也可以在你最喜欢的搜索引擎中使用“回文lisp”作为关键词来搜索其他解决方案。我不确定为什么使用
反向
效率不够;你真的分析过这个解决方案吗?只需遍历列表一次即可;与查找列表的长度相同,然后可以遍历两个列表进行比较
如果您想成为一个小爱好者,您可以同时找到列表的长度,并使用循环将其反转,如下所示:
(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)))))
此功能可避免使用反转:
(defun palindromp (a)
(or (null a)
(null (cdr a))
(and (equal (car a) (car (last a)))
(palindromp (butlast (cdr a))))))
以下是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))))
您以前是否使用过“标签”
!?给你(按计划):
这是二次消耗,比反向消耗更糟糕,反向消耗是线性的。我知道:-)但我认为OP要求太多了:使用反向大约是使用链表可以做到的最好的方法。我的回答几乎是一个笑话:是的,它避免了反转,但要付出一定的代价。。。至少我觉得它相当优雅,甚至不用“if”(在宏扩展之前!),这在列表长度上是二次的,而简单的(相等列表(反向列表))是线性的。请不要简单地发布代码。给出一些关于代码的解释、信息或用法。例如,请参见。
(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)))))
(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))))