时间复杂度:O(n)
空间复杂度:O(1)
解题思路:
(1)把链表对折分成前后两部分,关键在于找到链表中间节点的位置
(2)后半部分链表反转
(3)前半部分和后半部分的链表逐个比较元素是否一样,全部一样则是回文链表
参考题解都使用了快慢指针,我的理解快慢指针是为了找到中间节点的位置,时间复杂度也是两个指针把链表各走一遍, 我的代码中没有用快慢指针,先求链表长度,再找中间元素位置,时间复杂度也是把链表走了两遍,比快慢指针更容易理解
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
# 空链表不是回文链表
if not head:
return False
# 不是空链表
# 遍历链表得到链表的长度
n = 0
p = head
while p:
n += 1
p = p.next
print(n)
# 只有一个节点的链表是回文链表
if n == 1:
print('one')
return True
# 链表长度是偶数,找到中间节点,移动n//2次,作为第2个链表
if n%2 == 0:
q = head
for i in range(0, n//2):
q = q.next
# 链表长度是奇数,找到中间节点的后一个节点,移动(n//2+2)次作为第2个链表
else:
print(n//2)
q = head
for i in range(0, n//2):
q = q.next
# 将中间节点的前一个节点next指向None,把链表前后两半部分断开
k = q.next
q.next = None
q = k
# 此时q是后半部分链表的头节点
# 将后半部分链表反转
q = self.reverseList(q)
# 比较前半部分链表和反转后的后半部分链表元素值是否一致
p = head
while p and q:
# 如果p的值和q的值不一样,说明不是回文链表
if p.val != q.val:
return False
# p和q往后移动一个元素
p = p.next
q = q.next
# 此时p和q遍历结束,是回文链表
return True
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# Solution 1: 迭代法
# 维护指针p,它的next指向反转链表的头节点
p = ListNode(0)
# 维护指针q,它表示原始链表的当前节点
q = head
# 遍历原始链表,实现q的next指向p的next,同时更新p和q
while q:
k = q.next # 暂存q的next,防止形成环
q.next = p.next # q的next指向p的next,实现反转
p.next = q # 更新p的next
q = k # q往后移动一个节点
# 返回值是p的next
return p.next