目录
初级算法 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
题目源于力扣《初级算法》——《链表》中的《回文链表》一题,在题库中也可以查找得到。
本人小白一枚,如文内有错误望海涵,并指出错误。
题目:
题目很简单,判断一个链表是否为回文链表,如果是回文链表则返回True,否,则返回False。
解题思路:
在读完这道题的时候,我想了四种思路,其中有两条无法实现:
1. 建立空字典,使用指针遍历链表。如果字典中不存在链表节点的值,则在字典内填入,其中key为链表节点值,value统一赋值为0;如果有相同的值,则删除字典中的键值。最后判断字典内是否为空(链表节点数为偶数个,全部删除后则为空)或只有一个键(链表节点数为奇数),是则返回True, 否返回False。
弊端:出现[1, 2, 3, 3, 1, 2]这类链表则依然会返回True。
2. 反转整个链表。利用变量demo“拷贝”整个链表,并使用三指针将链表反转。得到反转后的链表与原链表进行对比(使用双指针),如果一一对应,则返回True,否返回False。
弊端:当我将整个链表反转的时候,原链表也被反转。(具体原因目前没有进行探究,初步猜测为没有拷贝链表节点)无论结果如何都返回True。
3. 栈。python中的列表可以直接当成栈来使用,append()相当于push(),pop()相当于删除末尾列表元素,这里需要得知链表的中间节点。
弊端:此时需要用一个额外的空间来储存链表节点值。
4. 反转前半部分链表。如果链表属于回文链表,那么前半部分反转后与后半部分完全相同。注意!这里还需要考虑链表的节点数,如果节点数为奇数,创立的变量index直接指向中间节点即可;如果节点数为偶数,我要求index指向的是第二部分的链表头。
我使用的是方法4。
解题步骤:
1. 判断链表中节点数是否为1:
如果链表只包含一个节点,进行下面的操作会报错,所以需要在开始的时候先进行判断。
代码如下:
cur = head.next
if cur == None:
return True
2. 获取链表长度:
这个步骤相对简单,我设置的链表长度是从0开始的。
index初始值为0,指针cur最初的所指应为head.next
index初始值为-1,指针cur最初的所指应为head
这样才能保证index是从0开始的
代码如下:
index = 0
while cur != None:
cur = cur.next
index += 1
3. 链表节点数为奇数:
这一步中包含两步:1. 反转链表;2. 比较链表节点的值是否相等
如果链表节点数为奇数,只需要反转中间的节点前的链表即可。(注意,index从0开始,index为偶数的时候,链表节点数为奇数)
反转结束后,需要比较链表节点的值。此时第二条链表应该从中间节点的下一个链表节点开始。
[1,2,3,2,1]
[2,1] [3,2,1]
即红色部分进行比较。
if index % 2 == 0: # 链表个数为奇数
index = index // 2
while index > 0: # 反转链表
cur.next = pre
pre = cur
cur = tem
tem = cur.next # tem是第三个指针,是cur.next
index -= 1
while tem != None: # 对比两个链表节点的值
if tem.val == pre.val: # 这里直接用tem,用cur.next也是一样的
tem = tem.next
pre = pre.next
else:
return False
return True
4. 链表节点数为偶数:
这一步中也包含两步:1. 反转链表;2. 比较链表节点的值是否相等
如果链表节点数为偶数,只需要反转中间的节点前的链表即可。但要注意,后半个链表则要从index所指的位置开始。
else:
index = index // 2 + 1
while index > 0:
cur.next = pre
pre = cur
cur = tem
tem = cur.next
index -= 1
while pre != None:
if cur.val == pre.val:
cur = cur.next
pre = pre.next
else:
return False
return True
附:
在最后提交之前,应该多举例不同的测试用例,避免提交后出现多种错误。
本题需要注意以下几个问题:
1. 是cur != None 还是cur.next != None?
2. index从0 开始和从1开始的循环条件有什么不同?