第一题 https://leetcode.cn/problems/swap-nodes-in-pairs/
python
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0, head)
cur = dummy
while cur.next and cur.next.next:
temp1 = cur.next
temp2 = cur.next.next.next
cur.next = cur.next.next
cur.next.next = temp1
temp1.next = temp2
cur = cur.next.next
return dummy.next

画图后会清晰好多,指针怎么指就好写了
第二题 https://leetcode.cn/problems/remove-nth-node-from-end-of-list/ 这个属于比较简单的,善用虚拟头结点和双指针
python
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode(0, head)
first = dummy
second = dummy
for i in range(n):
first = first.next
while first.next:
first = first.next
second = second.next
second.next = second.next.next
return dummy.next
第三题 https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/ 也比较简单
python
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
cur1 = headA
cur2 = headB
while cur1 != cur2:
cur1 = cur1.next if cur1 else headB
cur2 = cur2.next if cur2 else headA
return cur1
第四题 https://leetcode.cn/problems/linked-list-cycle-ii/ 难在理解怎么判断环和找到环的入口,这其实是算法上很经典的一个问题,大名鼎鼎的Floyd判圈算法,能自己想出来的人恭喜你,早出生几十年这个算法可能就是以你的名字命名了,我的水平理解这个算法都画了好久。。。。
1. 检测环的存在(龟兔赛跑)
-
兔子(快指针)每次走两步
-
乌龟(慢指针)每次走一步
-
如果有环,兔子一定会追上乌龟(因为肯定要进入环里面,相对速度为1,这样走一圈就相当于相遇了)
-
如果没环,兔子会先到达终点(None)
2. 找到环的入口(数学推导)
当兔子和乌龟第一次相遇后:
-
把乌龟放回起点
-
兔子和乌龟都改为每次走一步
-
它们再次相遇的点就是环的入口
数学证明(为什么能找入口):
设:
-
链表头到环入口距离:
a -
环入口到第一次相遇点距离:
b -
第一次相遇点到环入口距离:
c -
环周长:
L = b + c
第一次相遇时:
-
乌龟走的路程:
a + b -
兔子走的路程:
a + b + n*L(兔子可能已经在环里转了n圈) -
因为兔子速度是乌龟的2倍:
2(a + b) = a + b + n*L -
化简得:
a + b = n*L⇒a = n*L - b = (n-1)*L + c
结论 :从链表头走 a 步 = 从相遇点走 c 步 + (n-1) 圈
所以第二次相遇时,两者正好在环入口相遇!
python
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
fast = slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
return None