力扣题目链接
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
dummy_head = ListNode(next=head)
current = dummy_head
# 必须有cur的下一个和下下个才能交换,否则说明已经交换结束了
while current.next and current.next.next:
temp = current.next # 防止节点修改
temp1 = current.next.next.next
current.next = current.next.next
current.next.next = temp
temp.next = temp1
current = current.next.next
return dummy_head.next
这段代码的目标是交换链表中相邻节点的值,实现链表的两两节点交换。它通过迭代的方式来实现这个目标:
- 创建一个虚拟头节点 `dummy_head`,并将其 `next` 指向原始链表的头节点 `head`。
- 创建一个指针 `current` 并初始化为虚拟头节点,用于遍历链表。
- 使用 `while` 循环来遍历链表,确保至少有两个节点可供交换。
- 在循环中,暂存当前节点 `current` 和需要交换的两个相邻节点的引用,以便后续修改节点的连接。
- 交换相邻节点的值,将 `current` 的 `next` 指向下一个节点,同时将原第二个节点的 `next` 指向原第一个节点,完成交换。
- 保持链表连接,将原第一个节点的 `next` 指向原第三个节点。
- 移动 `current` 到已交换节点的下一个位置,准备进行下一轮交换。
- 最终,返回 `dummy_head.next`,即交换后链表的头节点。
力扣题目链接
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# 创建一个虚拟节点,并将其下一个指针设置为链表的头部
dummy_head = ListNode(0, head)
# 创建两个指针,慢指针和快指针,并将它们初始化为虚拟节点
slow = fast = dummy_head
# 快指针比慢指针快 n+1 步
for i in range(n+1):
fast = fast.next
# 移动两个指针,直到快速指针到达链表的末尾
while fast:
slow = slow.next
fast = fast.next
# 通过更新第 (n-1) 个节点的 next 指针删除第 n 个节点
slow.next = slow.next.next
return dummy_head.next
这段代码是用于删除单链表中倒数第 n 个节点的实现。以下是代码的逐行解释:
1. `dummy_head = ListNode(0, head)`:创建一个虚拟头节点 `dummy_head`,并将其 `next` 指针指向链表的头部 `head`。这个虚拟头节点的目的是简化处理链表头部的情况。
2. 创建两个指针 `slow` 和 `fast`,并将它们都初始化为虚拟头节点 `dummy_head`。这两个指针将在后续遍历链表中发挥作用。
3. `for i in range(n+1):`:这是一个循环,其中 `fast` 指针比 `slow` 指针快 `n+1` 步。这个循环的目的是将 `fast` 移动到距离 `slow` 恰好相隔 `n` 个节点的位置,以便后续删除倒数第 `n` 个节点。
4. `while fast:`:这是另一个循环,用于同时移动 `slow` 和 `fast` 指针,直到 `fast` 指针到达链表的末尾。此时,`slow` 指针将位于要删除的节点的前一个节点上。
5. `slow.next = slow.next.next`:通过这行代码,删除了第 `n` 个节点。具体来说,它将 `slow` 节点的 `next` 指针指向了 `slow.next.next`,跳过了第 `n` 个节点。
6. 最后,返回 `dummy_head.next`,即删除倒数第 `n` 个节点后的新链表的头节点。
这个算法通过使用两个指针,`slow` 和 `fast`,实现了删除倒数第 `n` 个节点的目标,同时避免了多次遍历链表。
同:160.链表相交
力扣题目链接
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
dis = self.getLength(headA) - self.getLength(headB)
# 通过移动较长的链表,使两链表长度相等
if dis > 0:
headA = self.moveForward(headA, dis)
else:
headB = self.moveForward(headB, abs(dis))
# 将两个头向前移动,直到它们相交
while headA and headB:
if headA == headB:
return headA
headA = headA.next
headB = headB.next
return None
def getLength(self, head: ListNode) -> int:
length = 0
while head:
length += 1
head = head.next
return length
def moveForward(self, head: ListNode, steps: int) -> ListNode:
while steps > 0:
head = head.next
steps -= 1
return head
这段代码是用于查找两个单链表的交点的实现。以下是代码的逐行解释:
1. `dis = self.getLength(headA) - self.getLength(headB)`:首先,计算两个链表的长度差,存储在变量 `dis` 中。这将帮助我们使两个链表的长度相等。
2. 如果 `dis > 0`,说明链表 A 较长,于是通过调用 `self.moveForward(headA, dis)` 将链表 A 的头节点向前移动 `dis` 步,以使两个链表的长度相等。
3. 如果 `dis <= 0`,说明链表 B 较长,于是通过调用 `self.moveForward(headB, abs(dis))` 将链表 B 的头节点向前移动 `abs(dis)` 步,以使两个链表的长度相等。
4. 接下来,使用循环遍历两个链表,同时移动它们的头节点,直到它们相交。如果在遍历过程中发现 `headA` 和 `headB` 相等,说明找到了交点,返回 `headA` 或 `headB`。
5. 如果循环结束后还没有找到交点,说明两个链表不相交,返回 `None`。
6. `getLength(self, head: ListNode) -> int`:这个方法用于计算链表的长度。通过遍历链表,每访问一个节点,增加计数器 `length`,最终返回链表的长度。
7. `moveForward(self, head: ListNode, steps: int) -> ListNode`:这个方法用于将链表头节点向前移动指定步数 `steps`。通过遍历链表,每移动一步,减少 `steps`,直到 `steps` 为 0,然后返回当前节点。
总的来说,这段代码通过计算链表长度差,使两个链表的头节点对齐,然后遍历链表找到交点。如果链表有交点,它会返回交点节点;如果没有,它会返回 `None`。
Java版,放进来是单纯被这个题解标题吸引。。。
`while` 循环内部的这两行代码:
```java
curA = (curA == null? headB : curA.next);
curB = (curB == null? headA : curB.next);
```
这两行代码是为了在两个链表中移动指针 `curA` 和 `curB`,并处理两个链表长度不同但有交点的情况。
1. `curA = (curA == null? headB : curA.next);`:这行代码的作用是移动 `curA` 指针。它首先检查 `curA` 是否为 `null`,也就是是否已经到达链表 `headA` 的末尾。如果 `curA` 是 `null`,说明链表 `headA` 已经走完了,此时将 `curA` 设置为链表 `headB` 的头节点,表示将 `curA` 跳到链表 `headB` 上。如果 `curA` 不是 `null`,则将 `curA` 向前移动一步,即 `curA.next`。
2. `curB = (curB == null? headA : curB.next);`:同样的逻辑,这行代码的作用是移动 `curB` 指针。它首先检查 `curB` 是否为 `null`,也就是是否已经到达链表 `headB` 的末尾。如果 `curB` 是 `null`,说明链表 `headB` 已经走完了,此时将 `curB` 设置为链表 `headA` 的头节点,表示将 `curB` 跳到链表 `headA` 上。如果 `curB` 不是 `null`,则将 `curB` 向前移动一步,即 `curB.next`。
这两行代码的目的是使 `curA` 和 `curB` 在两个链表中移动,并且在需要的情况下跳到对方的链表上,以处理两个链表长度不同但有交点的情况。通过这种方式,它们最终要么相遇在交点处,要么都到达链表的末尾,从而退出 `while` 循环。
力扣题目链接
lass Solution:
def detectCycle(self, head: ListNode) -> ListNode:
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# If there is a cycle, the slow and fast pointers will eventually meet
if slow == fast:
# Move one of the pointers back to the start of the list
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
# If there is no cycle, return None
return None