📅  最后修改于: 2023-12-03 15:42:07.879000             🧑  作者: Mango
在单向链表中找到所有回文数并求它们的总和是一个经典的算法问题。一个链表是回文的,当且仅当它可以从左向右和从右向左都被读取,而得到相同的序列。一个回文数则是满足上述条件的数字。因此,问题可以被分成两个部分:如何检查一个链表是否回文,以及如何找到所有回文数并计算它们的总和。
检查一个链表是否回文的一种简单方法是反转链表,然后比较反转前后的链表是否相同。具体的算法步骤如下:
这个算法的时间复杂度为 O(n),其中 n 是链表长度。
def is_palindrome(head):
# 前半部分链表不需要反转,因此可以直接用快慢指针法找中点
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 反转后半部分链表
prev = None
cur = slow
while cur:
next_node = cur.next
cur.next = prev
prev = cur
cur = next_node
# 比较前后两半部分链表是否相同
left = head
right = prev
while right:
if left.val != right.val:
return False
left = left.next
right = right.next
return True
找到所有回文数并计算总和的方法是,对每个节点都以它为起点,向后滑动一个指针来构建一个回文子序列。在遍历过程中,需要注意区分奇数长度和偶数长度的回文子序列。对于一个回文子序列,如果它的值和反转后的值相等,则它是一个回文数,可以累加到总和中。
这个算法的时间复杂度为 O(n^2),其中 n 是链表长度。
def palindrome_sum(head):
total = 0
cur = head
while cur:
# 奇数长度的回文子序列
prev = None
node = cur
while node:
p = node
node = node.next
p.next = prev
prev = p
if prev == cur:
break
left = cur
right = prev
while left and right and left.val == right.val:
left = left.next
right = right.next
if not left:
total += cur.val
# 偶数长度的回文子序列
pprev = None
pnode = cur.next
while pnode:
p = pnode
pnode = pnode.next
p.next = pprev
pprev = p
if pprev == cur:
break
left = cur
right = pprev
while left and right and left.val == right.val:
left = left.next
right = right.next
if not left:
total += cur.val
cur = cur.next
return total
以上就是检查一个链表是否回文和找到所有回文数并计算总和的完整算法。当然,我们这里也可以直接利用第一步的判断回文的算法,在遍历链表的同时直接判断是否回文,如果是则累加到总和中。