美文网首页
Python编程题47--回文链表

Python编程题47--回文链表

作者: wintests | 来源:发表于2022-01-23 10:01 被阅读0次

    题目

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

    例如:

    原链表转换为列表:[1, 2, 2, 1],返回结果:True

    原链表转换为列表:[1, 2],返回结果:False

    说明:

    • 返回结果时,链表中各节点的指向需要和最开始保持一致。

    已知 链表节点的定义、链表与列表相互转换 的代码如下:

    class ListNode:  # 单链表
        def __init__(self, val=0, next=None):
            self.val = val  # 链表节点上存储的元素
            self.next = next  # 指向下一个链表节点
    
    
    def list_to_list_node(numbers):  # 将列表转换为单向链表,并返回链表的头节点
        dummy_head = ListNode(0)
        pre = dummy_head
        for number in numbers:
            pre.next = ListNode(number)
            pre = pre.next
        pre = dummy_head.next
        return pre
    
    
    def list_node_to_list(node):  # 将单向链表转换为列表
        result = []
        while node:
            result.append(node.val)
            node = node.next
        return result
    

    实现思路1

    • 将原链表中所有数据存储到一个列表中,然后再判断是否回文
    • 判断列表是否回文,可以定义2个指针:left、right,一个从头开始往后移动,另一个从最后开始往前移动,每次判断指向的元素是否相同,如果不相同那么就说明不是回文,直接返回 False

    代码实现1

    class Solution:
        def isPalindrome(self, head: ListNode) -> bool:
            cur, length = head, 0
            result = []
            while cur is not None:  # 遍历链表,把所有节点上的元素都存储到列表 result 中
                length += 1
                result.append(cur.val)
                cur = cur.next
            left, right = 0, length - 1  # 定义2个指针,一个从头开始往后,另一个从最后开始往前
            while left < right:
                if result[left] != result[right]:  # 如果发现 left 和 right 对应的元素不一致,则说明不是回文
                    return False
                left += 1
                right -= 1
            return True
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(n)

    当然,我们在上面把链表元素都存储到列表 result 后,也可以直接将列表与其反转后的列表进行比较,代码如下:

    class Solution:
        def isPalindrome(self, head: ListNode) -> bool:
            cur = head
            result = []
            while cur is not None:  # 遍历链表,把所有节点上的元素都存储到列表 result 中
                result.append(cur.val)
                cur = cur.next
            return result == result[::-1]
    

    实现思路2

    • 使用 双指针 的方式来实现
    • 从链表中找到中间节点,将链表分为2部分:前半部分、后半部分,前半部分从原链表的头节点到中间节点,后半部分则是从原链表中间节点的下一个节点到最后节点
    • 反转原链表的后半部分,得到反转后的头节点 reverse_head
    • 定义一个变量,用于标记最终判断结果,默认为True
    • 遍历两个链表,前半部分链表从head开始移动,反转后半部分的链表从reverse_head开始移动,依次比较节点元素是否一致,如果不一致则将结果标记为 False ,同时 break 跳出循环
    • 比较结束后,因为原链表被分割成了两部分,所以需要先恢复原链表的指向,最后再返回最终判断结果即可

    代码实现2

    class Solution:
        def isPalindrome(self, head: ListNode) -> bool:
            if head is None:  # 如果是空链表,直接返回True
                return True
            middle_node = self.get_middle_node(head)  # 找到中间节点
            reverse_head = self.reverse_list_node(middle_node.next)  # 从原链表中间节点的下一个节点到最后节点,进行反转,并返回反转后的头节点
            flag, pre, post = True, head, reverse_head
            while post is not None:
                # 前半部分链表从head开始,后半部分反转后的链表从reverse_head开始,比较节点元素是否一致
                if pre.val != post.val:
                    flag = False
                    break
                pre = pre.next
                post = post.next
            middle_node.next = self.reverse_list_node(reverse_head)  # 恢复原链表
            return flag
    
        def get_middle_node(self, head: ListNode) -> ListNode:  # 找到链表的中间节点
            slow, fast = head, head  # 定义慢指针和快指针
            while fast.next is not None and fast.next.next is not None:
                slow = slow.next  # 慢指针每次移动1位
                fast = fast.next.next  # 快指针每次移动2位
            return slow
    
        def reverse_list_node(self, head: ListNode) -> ListNode:  # 反转链表, 返回反转后的头节点
            pre, cur = None, head
            while cur is not None:
                next_node = cur.next
                cur.next = pre
                pre = cur
                cur = next_node
            return pre
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    更多Python编程题,等你来挑战:Python编程题汇总(持续更新中……)

    相关文章

      网友评论

          本文标题:Python编程题47--回文链表

          本文链接:https://www.haomeiwen.com/subject/loiucrtx.html