📜  链表中所有回文数的总和(1)

📅  最后修改于: 2023-12-03 15:42:07.879000             🧑  作者: Mango

链表中所有回文数的总和

在单向链表中找到所有回文数并求它们的总和是一个经典的算法问题。一个链表是回文的,当且仅当它可以从左向右和从右向左都被读取,而得到相同的序列。一个回文数则是满足上述条件的数字。因此,问题可以被分成两个部分:如何检查一个链表是否回文,以及如何找到所有回文数并计算它们的总和。

检查链表是否回文

检查一个链表是否回文的一种简单方法是反转链表,然后比较反转前后的链表是否相同。具体的算法步骤如下:

  1. 用快慢指针法找到链表中点
  2. 反转后半部分链表
  3. 用两个指针同时从链表头和中点开始依次比较值,如果比较到任意一个不相等,则链表不是回文的。

这个算法的时间复杂度为 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

以上就是检查一个链表是否回文和找到所有回文数并计算总和的完整算法。当然,我们这里也可以直接利用第一步的判断回文的算法,在遍历链表的同时直接判断是否回文,如果是则累加到总和中。