LeetCode回文链表 双指针+反转链表
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:head = [1,2,2,1]输出:true
示例 2:
输入:head = [1,2]输出:false
思路:
要判断链表是否是回文链表,我们自然是希望可以用两个指针,一个从前向后走,另一个从后向前走,然后逐一比较直到两个指针相遇了。
然而,链表不是数组,怎么可以从后向前遍历呢?但没关系,没有条件我们可以创造条件——我们原来做过反转链表的题目,我们可以把链表的后半段进行反转,这样我们对反转的链表进行遍历,就相当于从后往前对原链表进行遍历了。
那怎么反转链表的后半段呢?是不是只要找到链表的中间节点,交给我们定义的反转链表函数就好了。那怎么找到链表的中间节点呢?原来我们对链表进行归并排序时也用过:用快慢指针呀!
没想到短短的一个题,用到了之前做题用过的很多常见技巧,算是一个复习综合题了~
虽然总体思路有了,但写起代码来还是有很地方需要注意的。比如找后半段链表的时候,根据原链表自身长度的奇偶会有不同,需要自己处理一下,主要是因为奇数链表的中间结点我们是不考虑的。
因为right判断终点的条件是while(right and right.next),假如right最后是终止在节点处,则链表是奇数个,left需要取下一个,当成后半段的头结点,再次强调是这是因为奇数链表的中间结点我们是不考虑的;假如right最后是终止在节点后的None处,则链表是偶数个,left不用动,就是后半段的头结点。
代码:
class Solution(object):
def isPalindrome(self, head):
def reverse(head):#经典 非递归法反转链表 具体细节就不写注释了 有专门的题
pre=None
cur=head
nex=None
while(cur):
nex = cur.next
cur.next=pre
pre = cur
cur=nex
return pre
left=head#定义快慢指针 left和right
right=head
while(right and right.next):#假如快指针到头
left=left.next
right=right.next.next
if right!=None:# right最后不为空 链表长是奇数 left要变成下一个
left=left.next
ch = reverse(left)#对后半段反转
while ch:#对后半段元素逐一和前半段比较
if head.val!=ch.val:#一旦有元素不同就不是回文链表
return False#直接返回
head=head.next
ch=ch.next
return True#若能顺利遍历结束,则是回文链表
小结:
代码中的反转链表我就用的之前写过的非递归的迭代方法,这个基本上可以当成工具函数默写出来了。对于奇偶的判断我加了点图,应该就很好理解了(感觉画图还是个挺费时间的事~)。
除了判断奇偶长度上有一点小特殊处理外,我们最后逐一比较的时候是用的while ch,这样就可以只考虑后半段的长度,也巧妙地把奇数情况下的中间节点忽略,也是一个简洁高效的写法。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了