Leetcode 234. 回文链表 快慢指针+链表逆序实现O(n)时间复杂度且O(1)空间复杂度

题目要求

判断一个链表是否为回文链表。

解题思路

不限制时间复杂度的情况下是非常简单的题目,可以有多种方法完成本题。

如果限制了 O ( n ) O(n) O(n) 时间复杂度且 O ( 1 ) O(1) O(1) 空间复杂度那么可以按照以下思路。

链表题中看到 O ( n ) O(n) O(n) 时间复杂度且 O ( 1 ) O(1) O(1) 空间复杂度可以考虑快慢指针就相当于数组题看到 O ( n ) O(n) O(n) 时间复杂度且 O ( 1 ) O(1) O(1) 空间复杂度可以考虑双指针一样。

那么从快慢指针开始思考。我们知道,快慢指针可以找链表的中点。回文链表只需要对链表中点两边进行比较就可以知道结果,因此先用快慢指针找到链表的中点。

找到中点以后需要令前半部分末尾等于 N o n e None None,因此为了方便起见,前半部分找到中点左边的一个点,就停止。假设中间节点是 m e d i a n median median,我们希望 s l o w slow slow 停留在 m e d i a n median median 的左边第一个节点,这样我们只要令 s l o w . n e x t = N o n e slow.next = None slow.next=None 就可以得到左半部分链表。

此时右半部分链表只需要令 c u r = s l o w . n e x t cur = slow.next cur=slow.next,这样 c u r cur cur 就是右半链表。

利用双指针反转链表的方式,反转链表之后进行比较节点的值就可以得到结果。在比较的时候,我们之前这样处理以后,右半部分一定不大于左半部分的长度,因此遍历右半部分,这样如果链表长度是奇数的时候,不需要考虑中间节点。

以下用多张图具体说明这个过程:

  • 链表长度是奇数

ppt1.jpg2.ppt2.jpg3.ppt3.jpg4.ppt4.jpg5.ppt5.jpg6.ppt6.jpg7.ppt7.jpg8.ppt8.jpg9.ppt9.jpg10.ppt10.jpg11.ppt11.jpg12.ppt12.jpg13.ppt13.jpg

  • 链表长度是偶数时,可以尝试用同样的方式处理

代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        if not head:
            return True
        fast = slow = head
        while fast.next and fast.next.next:
            fast = fast.next.next
            slow = slow.next
        pre = None
        cur = slow.next
        slow.next = None
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        while pre:
            if head.val != pre.val:
                return False
            head = head.next
            pre = pre.next
        return True

复杂度分析

时间复杂度  O ( n ) O(n) O(n) 其中 n n n 是链表的长度
空间复杂度  O ( 1 ) O(1) O(1) 没有使用额外空间

工作之余刷刷题写写题解,我的Leetcode主页

https://leetcode-cn.com/u/airesearcherjhm/

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页