今天是周天,本来可以休息一天,但是考虑到昨天还有两道题目没有完成,于是继续打卡。
题目1.
07.链表相交
*附一个思路强大、简洁但不简单的代码(膜拜)希望有人能给我讲解一下
个人认为比较好的讲解思路链接:
https://www.bilibili.com/video/BV1u341187v3/share_source=copy_web&vd_source=1261b97a33f42388f92b473554874c36
Python版本代码:
考虑使用双指针的方法来解决问题,同时考虑链表长度可能不同的情况。
class Solution:
def getIntersectionNode(self, headA, headB):
#首先,通过遍历链表headA和headB,分别计算出它们的长度lenA和lenB。这是通过两个循环实现的,每个循环使用一个指针cur遍历链表,每遍历一个节点,长度就增加1
lenA, lenB = 0, 0
cur = headA
while cur: # 求链表A的长度
cur = cur.next
lenA += 1
cur = headB
while cur: # 求链表B的长度
cur = cur.next
lenB += 1
curA, curB = headA, headB
'''
接下来,代码通过比较lenA和lenB的大小,决定哪个链表更长。为了让两个指针在相同的起点 开始遍历(即它们同时到达链表末尾或者相交点的位置),较长的链表需要比较短的链表多走一些步数。
如果lenA > lenB,则交换curA和curB,以及lenA和lenB的值,确保curB指向较长链表的头节点,lenB为较长链表的长度。
然后,通过for循环让curB向前移动 (lenB - lenA) 步,这样curA和curB就位于距离链表末尾相同距离的位置了, 如果链表相交,则位于相交点;如果不相交,则都位于末尾的None。
'''
if lenA > lenB: # 让curB为最长链表的头,lenB为其长度
curA, curB = curB, curA
lenA, lenB = lenB, lenA
for _ in range(lenB - lenA): # 让curA和curB在同一起点上(末尾位置对齐)
curB = curB.next
'''
最后,使用两个指针curA和curB同时遍历两个链表。由于它们现在位于距离链表末尾相同距离的位置,所以它们要么同时到达链表末尾(如果链表不相交),要么在相交点相遇。
使用一个while循环遍历链表,直到curA或curB到达链表末尾(None)。在每次循环中,检查curA和curB是否相等。如果相等,则说明它们相遇在相交点,返回该节点。
while curA:
# 遍历curA 和 curB,遇到相同则直接返回
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
#如果循环结束都没有返回,则说明链表不相交,返回None。
return None
总结&分析交换的原因
在解决两个链表相交问题时,如果链表A的长度大于链表B的长度,则进行curA
和curB
以及lenA
和lenB
的交换操作,主要是出于优化遍历过程、确保两个指针能够同时到达链表末尾(如果链表不相交)或相交点(如果链表相交)的考虑。
交换原因分析
-
确保同时遍历:
当两个链表长度不等时,直接从一个链表的头节点开始遍历到另一个链表的头节点会导致它们在遍历过程中永远无法“对齐”。例如,如果链表A比链表B长,那么当遍历完链表B后,链表A的指针还没有到达末尾。通过交换,我们可以确保较长的链表(curB
)的指针在遍历过程中“等待”较短的链表(curA
)的指针,以便两者能在某个点(相交点或末尾)相遇。 -
简化逻辑:
交换后,我们可以使用一个统一的循环来处理两个链表的遍历,而不需要编写额外的逻辑来处理不同长度的链表。这样可以使代码更加简洁和易于理解。
题目2.
环形链表II
题目链接. - 力扣(LeetCode)
讲解链接把环形链表讲清楚! 如何判断环形链表?如何找到环形链表的入口? LeetCode:142.环形链表II_哔哩哔哩_bilibili
颇有挑战,笔者实力有限,读者可参考链接。
总结:要掌握链表的基本操作(增删改查),以及虚拟头结点的技巧,最后结合快慢指针和迭代、递归等技巧。