234. 回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

示例 1:

输入:head = [1,2,2,1]
输出:true

示例 2:

输入:head = [1,2]
输出:false

提示:

  • 链表中节点数目在范围[1, 10^5] 内
  • 0 <= Node.val <= 9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一解

先找到链表中间,再将另一半链表反转。比如找到中间 [1,2(mid),2,1] ,将链表反转后[1(first),2,1(second),2] ,然后迭代比较 first 和 second 即可。

  • 可使用快慢指针找到 mid :慢指针每次移动一次,快指针每次移动两次。
  • 可使用多指针反转链表(参见 leetcode 206)。
# 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: ListNode) -> bool:
        if not head: return False
        mid_node = self.find_mid_position(head)
        second_start = self.reverse_link_node(mid_node.next)
        second_node = second_start
        first_node = head
        res = True
        while res and second_node:
            if second_node.val != first_node.val:
                res = False
            second_node = second_node.next
            first_node = first_node.next
				# 最后恢复链表
        mid_node.next = self.reverse_link_node(second_start)
        return res

    def find_mid_position(self, head):
        slow = head
        fast = head
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
        return slow
    
    def reverse_link_node(self, node):
        pre = None
        cur = node
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        return pre
  • 时间复杂度 O(n) :n 为链表长度。
  • 空间复杂度 O(1)。