算法刷题打卡第60天:回文链表

回文链表

难度:简单

给定一个链表的 头节点 head ,请判断其是否为回文链表。

如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

示例 1:

请添加图片描述

输入: head = [1,2,3,3,2,1]
输出: true

示例 2:

请添加图片描述

输入: head = [1,2]
输出: false

解法一、将值复制到数组中后用双指针法

思路:

一共为两个步骤:

  1. 复制链表值到数组列表中。
  2. 使用双指针法判断是否为回文。

第一步,我们需要遍历链表将值复制到数组列表中。每次迭代向数组添加 head.val,并更新 head = head.next,当 head = null 时停止循环。

第二步,使用双指针法来检查是否为回文。我们在起点放置一个指针,在结尾放置一个指针,每一次迭代判断两个指针指向的元素是否相同,若不同,返回 false;相同则将两个指针向内移动,并继续判断,直到两个指针相遇。

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

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        lis = []
        while head:
            lis.append(head.val)
            head = head.next
        l, r = 0, len(lis) - 1
        while l < r:
            if lis[l] != lis[r]:
                return False
            l += 1
            r -= 1
        return True

解法二、快慢指针 + 反转链表

思路:
避免使用 O ( n ) O(n) O(n) 额外空间的方法就是改变输入。

我们可以将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较。

该方法虽然可以将空间复杂度降到 O ( 1 ) O(1) O(1),但是在并发环境下,该方法也有缺点。在并发环境下,函数运行时需要锁定其他线程或进程对链表的访问,因为在函数执行过程中链表会被修改。

整个流程可以分为以下四个步骤:

  1. 找到前半部分链表的尾节点:
    我们可以计算链表节点的数量,然后遍历链表找到前半部分的尾节点。
    我们也可以使用快慢指针在一次遍历中找到:慢指针一次走一步,快指针一次走两步,快慢指针同时出发。当快指针移动到链表的末尾时,慢指针恰好到链表的中间。通过慢指针将链表分为两部分。
  2. 反转后半部分链表:
    可以使用「206. 反转链表」问题中的解决方法来反转链表的后半部分。
  3. 判断是否回文:
    比较两个部分的值,当后半部分到达末尾则比较完成,可以忽略计数情况中的中间节点。
  4. 返回结果。

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

class Solution:
    def reversal(self, root):
        prev = None
        while root:
            temp = root.next
            root.next = prev
            prev = root
            root = temp
        return prev

    def isPalindrome(self, head: ListNode) -> bool:
        s, q = head, head
        while q is not None and q.next is not None:
            s = s.next
            q = q.next.next
        if q:
            s = s.next
        s = self.reversal(s)
        while s:
            if s.val != head.val:
                return False
            s = s.next
            head = head.next
        return True

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/aMhZSa

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏秃然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值