思路:
将链表反转,然后和原链表对比,如果相等即为回文链表。
- 记录当前节点和之前和之后的节点
- 将当前节点的指针反转,由指向后一个节点改为指向前一个节点(没有前面节点时, 指向None)
- 依次处理下一个数据,直到最后一个数据,将其指向新链表的头即可
代码如下, 定义一个反转链表的函数reverse
In [10]: class Node:
...: def __init__(self, value, next=None):
...: self.value = value
...: self.next = next
...: def __repr__(self):
...: head = self
...: repr = ''
...: while head:
...: repr += f'{head.value} -> '
...: head = head.next
...: repr += 'None'
...: return repr
In [11]: def reverse(node):
...: former = None
...: while node.next:
...: latter = node.next
...: node.next = former # 重定向指针方向
...: former, node = node, latter # 移动当前节点和之前节点的位置
...: node.next = former # 最后一个节点指向新链表的头
...: return node
In [12]: node6 = Node(6)
...: node5 = Node(5, node6)
...: node4 = Node(4, node5)
...: node3 = Node(3, node4)
...: node2 = Node(2, node3)
...: node1 = Node(1, node2)
In [13]: node1
Out[13]: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> None
In [14]: reversed_node = reverse(node1)
In [15]: reversed_node
Out[15]: 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> None
In [16]: from copy import deepcopy
...: def is_palindrome(node):
...: node_copy = deepcopy(node)
...: reversed_node = reverse(node_copy)
...: print(node)
...: print(reversed_node)
...: while node:
...: if not node.value == reversed_node.value:
...: return False
...: node, reversed_node = node.next, reversed_node.next
...: return True
In [17]: is_palindrome(node1)
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> None
6 -> 5 -> 4 -> 3 -> 2 -> 1 -> None
Out[17]: False
In [18]: node6 = Node(1)
...: node5 = Node(2, node6)
...: node4 = Node(3, node5)
...: node3 = Node(3, node4)
...: node2 = Node(2, node3)
...: node1 = Node(1, node2)
In [19]: is_palindrome(node1)
1 -> 2 -> 3 -> 3 -> 2 -> 1 -> None
1 -> 2 -> 3 -> 3 -> 2 -> 1 -> None
Out[19]: True
② 提高性能的方法
结合 单向链表的中间节点, 可以找到链表的中点后,反转后一半儿链表,然后和原链表的前一半进行比较。
In [1]: class Node:
...: def __init__(self, value, next=None):
...: self.value = value
...: self.next = next
...: def __repr__(self):
...: head = self
...: repr = ''
...: while head:
...: repr += f'{head.value} -> '
...: head = head.next
...: repr += 'None'
...: return repr
In [2]: def get_middle(node):
...: slow, fast = node, node
...: while fast and fast.next:
...: slow = slow.next
...: fast = fast.next.next
...: return slow
...:
In [3]: def reverse(node):
...: former = None
...: while node.next:
...: latter = node.next
...: node.next = former
...: former, node = node, latter
...: node.next = former
...: return node
...:
In [4]: def is_palindrome(node):
...: middle = get_middle(node)
...: reversed_half = reverse(middle)
...: while reversed_half:
...: if not node.value == reversed_half.value:
...: return False
...: node, reversed_half = node.next, reversed_half.next
...: return True
In [5]: node6 = Node(1)
...: node5 = Node(2, node6)
...: node4 = Node(3, node5)
...: node3 = Node(3, node4)
...: node2 = Node(2, node3)
...: node1 = Node(1, node2)
In [6]: is_palindrome(node1)
Out[6]: True