• LeetCode 234. 回文链表


    234. 回文链表

    题目:给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
    链接 https://leetcode.cn/problems/palindrome-linked-list/

    个人思路

    1. 将值复制到数组中后用双指针法
    class Solution:
        def isPalindrome(self, head: Optional[ListNode]) -> bool:
            value = []
            while head:
                value.append(head.val)
                head = head.next
            left = 0
            right = len(value)-1
            while left < right:
                if value[left] != value[right]:
                    return False
                else:
                    left += 1
                    right -= 1
            return True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    但官方代码有点秀:反转列表后直接对比是否和原列表相等;

    class Solution:
        def isPalindrome(self, head: ListNode) -> bool:
            vals = []
            current_node = head
            while current_node is not None:
                vals.append(current_node.val)
                current_node = current_node.next
            return vals == vals[::-1]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    时间复杂度:O(n),其中 n 指的是链表的元素个数。
    空间复杂度:O(n),其中 n 指的是链表的元素个数,我们使用了一个数组列表存放链表的元素值。

    官方思路

    1. 递归
      在这里插入图片描述
    class Solution:
        def isPalindrome(self, head: ListNode) -> bool:
    
            self.front_pointer = head
    
            def recursively_check(current_node=head):
                if current_node is not None:
                    if not recursively_check(current_node.next):
                        return False
                    if self.front_pointer.val != current_node.val:
                        return False
                    self.front_pointer = self.front_pointer.next
                return True
    
            return recursively_check()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    复杂度分析
    (1)时间复杂度:O(n),其中 n 指的是链表的大小。
    (2)空间复杂度:O(n),其中 n 指的是链表的大小。我们要理解计算机如何运行递归函数,在一个函数中调用一个函数时,计算机需要在进入被调用函数之前跟踪它在当前函数中的位置(以及任何局部变量的值),通过运行时存放在堆栈中来实现(堆栈帧)。在堆栈中存放好了数据后就可以进入被调用的函数。在完成被调用函数之后,他会弹出堆栈顶部元素,以恢复在进行函数调用之前所在的函数。在进行回文检查之前,递归函数将在堆栈中创建 n 个堆栈帧,计算机会逐个弹出进行处理。所以在使用递归时空间复杂度要考虑堆栈的使用情况。
    (3)这种方法不仅使用了 O(n) 的空间,且比第一种方法更差,因为在许多语言中,堆栈帧的开销很大(如 Python),并且最大的运行时堆栈深度为 1000(可以增加,但是有可能导致底层解释程序内存出错)。为每个节点创建堆栈帧极大的限制了算法能够处理的最大链表大小。

    作者:LeetCode-Solution
    链接:https://leetcode.cn/problems/palindrome-linked-list/solution/hui-wen-lian-biao-by-leetcode-solution/

    1. 快慢指针

    在这里插入图片描述
    在这里插入图片描述

    class Solution:
    
        def isPalindrome(self, head: ListNode) -> bool:
            if head is None:
                return True
    
            # 找到前半部分链表的尾节点并反转后半部分链表
            first_half_end = self.end_of_first_half(head)
            second_half_start = self.reverse_list(first_half_end.next)
    
            # 判断是否回文
            result = True
            first_position = head
            second_position = second_half_start
            while result and second_position is not None:
                if first_position.val != second_position.val:
                    result = False
                first_position = first_position.next
                second_position = second_position.next
    
            # 还原链表并返回结果
            first_half_end.next = self.reverse_list(second_half_start)
            return result    
    
        def end_of_first_half(self, head):
            fast = head
            slow = head
            while fast.next is not None and fast.next.next is not None:
                fast = fast.next.next
                slow = slow.next
            return slow
    
        def reverse_list(self, head):
            previous = None
            current = head
            while current is not None:
                next_node = current.next
                current.next = previous
                previous = current
                current = next_node
            return previous
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    复杂度分析
    时间复杂度:O(n),其中 n 指的是链表的大小
    空间复杂度:O(1)。我们只会修改原本链表中节点的指向,而在堆栈上的堆栈帧不超过 O(1)。

    作者:LeetCode-Solution
    链接:https://leetcode.cn/problems/palindrome-linked-list/solution/hui-wen-lian-biao-by-leetcode-solution/

  • 相关阅读:
    工程伦理--16.1传统制造业的转型升级与伦理问题
    EtherCAT总线伺服速度控制功能块(H5U PLC)
    面试:dumpsys meminfo 内存信息含义
    c++ 左值引用 右值引用 及 参数引用 & 与&&
    mysql:如何设计互相关注业务场景
    重保主题公开课举办,实战专家分享能源行业安全防护的破局之道
    RL-D1电流继电器
    牛客网之SQL非技术快速入门(9)-综合练习
    解释 Git 的基本概念和使用方式。
    【MySQL数据库笔记 - 进阶篇】(四)视图/存储过程/触发器
  • 原文地址:https://blog.csdn.net/weixin_48127034/article/details/126299076