【LeetCode HOT100】234. 回文链表

加载中... 浏览

题目

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

示例 1:

输入:head = [1,2,2,1]
输出:true
回文链表示意图

提示

一句话思路:先找链表中间节点,反转后半段,再逐个比较前后两半是否相同

  • 找中间节点用快慢指针:slow 每次走一步,fast 每次走两步,fast 到末尾时 slow 正好在中点。
  • 反转从 mid 开始的后半段,得到 head2,然后让 head(前半段)和 head2(反转后的后半段)从头同步比较。
  • 前半段和后半段长度相等(奇数个节点时中间节点被归入后半段,不影响比较结果),有任一节点不同就不是回文。
  • 时间 O(n)、空间 O(1)(不额外开辟链表,反转是原地操作)。

答案

python
class Solution:
    # 876. 链表的中间结点
    def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = fast = head          # 快慢指针都从头节点出发
        while fast and fast.next:   # fast 每次能走两步才继续
            slow = slow.next        # slow 每次走一步
            fast = fast.next.next   # fast 每次走两步
        return slow                 # fast 到末尾时,slow 正好在中间节点

    # 206. 反转链表
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        pre, cur = None, head       # pre 已反转头,cur 当前节点
        while cur:                  # 遍历到链表末尾
            nxt = cur.next          # 暂存后继节点
            cur.next = pre          # 当前节点指向前一个节点(反转)
            pre = cur               # pre 前进
            cur = nxt               # cur 前进到原后继节点
        return pre                  # 反转后的链表头

    def isPalindrome(self, head: Optional[ListNode]) -> bool:
        mid = self.middleNode(head)             # 找中间节点
        head2 = self.reverseList(mid)           # 反转后半段
        while head2:                            # 逐对比较前后两半
            if head.val != head2.val:           # 对应节点值不同
                return False                    # 不是回文链表
            head = head.next                    # 前半段指针后移
            head2 = head2.next                  # 后半段指针后移
        return True                             # 全部相同,是回文链表

留言板

加载评论中...
【LeetCode HOT100】21. 合并两个有序链表
【LeetCode HOT100】121. 买卖股票的最佳时机
Valaxy v0.28.0-beta.1 驱动|主题-Yunv0.28.0-beta.1