【leetcode】回文链表

时间复杂度:O(n)
空间复杂度:O(1)
解题思路:
(1)把链表对折分成前后两部分,关键在于找到链表中间节点的位置
(2)后半部分链表反转
(3)前半部分和后半部分的链表逐个比较元素是否一样,全部一样则是回文链表
参考题解都使用了快慢指针,我的理解快慢指针是为了找到中间节点的位置,时间复杂度也是两个指针把链表各走一遍, 我的代码中没有用快慢指针,先求链表长度,再找中间元素位置,时间复杂度也是把链表走了两遍,比快慢指针更容易理解

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def isPalindrome(self, head: Optional[ListNode]) -> bool:
        # 空链表不是回文链表
        if not head:
            return False
        
        # 不是空链表
        # 遍历链表得到链表的长度
        n = 0
        p = head
        while p:
            n += 1
            p = p.next
        print(n)
        # 只有一个节点的链表是回文链表
        if n == 1:
            print('one')
            return True
        # 链表长度是偶数,找到中间节点,移动n//2次,作为第2个链表
        if n%2 == 0:
            q = head
            for i in range(0, n//2):
                q = q.next
        # 链表长度是奇数,找到中间节点的后一个节点,移动(n//2+2)次作为第2个链表
        else:
            print(n//2)
            q = head
            for i in range(0, n//2):
                q = q.next
            # 将中间节点的前一个节点next指向None,把链表前后两半部分断开
            k = q.next
            q.next = None
            q = k
        # 此时q是后半部分链表的头节点
        # 将后半部分链表反转
        q = self.reverseList(q)
        # 比较前半部分链表和反转后的后半部分链表元素值是否一致
        p = head
        while p and q:
            # 如果p的值和q的值不一样,说明不是回文链表
            if p.val != q.val:
                return False
            # p和q往后移动一个元素
            p = p.next
            q = q.next
        # 此时p和q遍历结束,是回文链表
        return True

    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # Solution 1: 迭代法
        
        # 维护指针p,它的next指向反转链表的头节点 
        p = ListNode(0) 
        # 维护指针q,它表示原始链表的当前节点
        q = head
        # 遍历原始链表,实现q的next指向p的next,同时更新p和q
        while q:
            k = q.next # 暂存q的next,防止形成环
            q.next = p.next # q的next指向p的next,实现反转
            p.next = q # 更新p的next
            q = k # q往后移动一个节点
        # 返回值是p的next
        return p.next
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值