题目描述
思路
看到这个题,当然最简单的方法就是变成字符串,然后用字符串判断
不过,这样太Low了,想想别的办法
借鉴一下字符串的回文判断,是从两头向中间逐个遍历对比
但是链表它本身是单向的,没有向前的指针,只有向后的。也就是说,从前往后遍历是很简单的,但是从后往前可就不太容易了,所以借助链表本身肯定不行,还得借助别的方法,能够从后向前的。
这里想到栈,因为对于链表而言,从前向后,我们可以进栈,从后向前,正好我们可以利用出栈来实现从后向前的遍历
别急,你要是看到这里就去写下了这样一行:
class Stack:
好了,你又Low了,这样自定义一个数据结构,来实现回文链表的判定,那跟我用数组有什么区别呢。同样都是借助了别的数据结构来实现,至少得定义这样的数据结构
那栈还能怎么用?
没错就是递归,写一个递归函数,从而让他的栈存在于调用过程中,岂不妙哉
代码实现
这次代码讲解部分我采用当时编写时的思路,一点一点把代码放上来
这次测试用的是数组 [1, 2, 3, 4, 6, 4, 3, 2, 1]
直接用力扣官方的代码
首先,我们既然需要前后对比,在递归调用时,必须要直接让一个指针到达链表尾部,同时内存栈中已经存放下了前面所有的调用
def recursively_check(current_node=head):
if current_node is not None:
if not recursively_check(current_node.next):
到这里,内存栈就已经放下了之前所有的调用,每一次调用对应一个节点,直到current node为空为止
好了,这一层调用该结束了,那这里应该返回True才行,False的话,就需要一路返回False回主进程了。
def recursively_check(current_node=head):
if current_node is not None:
if not recursively_check(current_node.next):
return False
return True
返回True之后,进行判断该层的current_node的value是否和前面对应的front_node的value相等,那么也就是说,在每一次调用该函数的时候,前面也需要一个指针并不停向后移动
所以,这里加上判断语句
def recursively_check(current_node=head):
if current_node is not None:
if not recursively_check(current_node.next):
return False
if self.front_pointer.val != current_node.val:
return False
return True
再加上一个front_node,作为从前向后的指针
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
self.front_pointer = head
def recursively_check(current_node=head):
if current_node is not None:
if not recursively_check(current_node.next):
return False
if self.front_pointer.val != current_node.val:
return False
self.front_pointer = self.front_pointer.next
return True
return recursively_check()
然后这个代码就编写完成了,成功使用了递归调用,实现了链表从后向前的访问
感兴趣的大家可以把这段完整的代码复制到自己本地的编译器中,然后debug看一下执行的流程
自己造了两个轮子:ListNode和list_to_listNode
class ListNode:
__slots__ = ('val', 'next')
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def list_to_listNode(list) -> ListNode:
dummy = ListNode()
ptr = dummy
for element in list:
ptr.next = ListNode(element)
ptr = ptr.next
return dummy.next
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
self.front_pointer = head
def recursively_check(current_node=head):
if current_node is not None:
if not recursively_check(current_node.next):
return False
if self.front_pointer.val != current_node.val:
return False
self.front_pointer = self.front_pointer.next
return True
return recursively_check()
if __name__ == '__main__':
print(Solution().isPalindrome(list_to_listNode([1, 2, 3, 4, 6, 4, 3, 2, 1])))