• Python编程题47回文链表


    题目

    给你一个单链表的头节点 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编程题汇总(持续更新中……)

  • 相关阅读:
    VUE iframe消息通信postMessage
    sqlserver 增加新列并加备注说明备用
    实用的apipost 软件,登录token改变,其他请求也随之改变自带token请求设置
    介绍一下magic.net多租户的应用
    vue 给路由增加自定义信息meta属性
    hyperv 设置NAT网络备忘
    mybatis plus 多字段排序
    c#使用redis
    centos ssh连接卡在【To escape to local shell, press 'Ctrl+Alt+]'.】的解决方法
    java stream 转字符串数组
  • 原文地址:https://www.cnblogs.com/wintest/p/15835784.html
Copyright © 2020-2023  润新知