787 words
4 minutes
日拱两卒(八)
2026-08-06

30#

两两交换链表中的节点。

和K个一组翻转没区别。

class Solution:
def reverse(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = head
pre = None
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0, head)
cur = dummy.next
cur_head = cur
pre_cur_head = dummy
cnt = 0
while cur:
cnt += 1
nxt = cur.next
if cnt >= 2:
cur.next = None
new_head = self.reverse(cur_head)
cur_head.next = nxt
pre_cur_head.next = new_head
pre_cur_head = cur_head
cur_head = nxt
cnt = 0
cur = nxt
return dummy.next

29#

删除链表的倒数第N个节点。

尺子一开始左端点在链表头,右端点在正数第N个,那么尺子右端点在链表尾时,左端点就在倒数第N个。

删除其实是要找第N+1个。

class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
left = right = dummy = ListNode(0, head)
for _ in range(n):
right = right.next
while right.next:
left = left.next
right = right.next
left.next = left.next.next
return dummy.next

28#

两数相加。

简单模拟。

class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0, None)
carry = 0
cur = dummy
while l1 or l2:
val = carry
val += l1.val if l1 else 0
val += l2.val if l2 else 0
new_node = ListNode(val % 10, None)
cur.next = new_node
carry = val // 10
cur = cur.next
l1 = l1.next if l1 else l1
l2 = l2.next if l2 else l2
if carry:
new_node = ListNode(carry, None)
cur.next = new_node
return dummy.next

27#

合并两个有序链表。

之前合并K个也做过了。

class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0, None)
cur = dummy
while list1 and list2:
if list1.val < list2.val:
cur.next = ListNode(list1.val, None)
list1 = list1.next
else:
cur.next = ListNode(list2.val, None)
list2 = list2.next
cur = cur.next
if list1:
cur.next = list1
else:
cur.next = list2
return dummy.next

26#

环形链表II。

找环的第一个节点。题解太诡异了,完全不如直接哈希。

class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
mp = {}
while head:
if mp.get(head):
return head
mp[head] = True
head = head.next
return None

25#

环形链表。

快慢指针看是否相遇以判环。

class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False

24#

回文链表。

把后半段翻转,逐位比对。

class Solution:
def middle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
def reverse(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = head
pre = None
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
def isPalindrome(self, head: Optional[ListNode]) -> bool:
if head.next is None:
return True
head2 = self.reverse(self.middle(head))
while head and head2:
if head.val != head2.val:
return False
head = head.next
head2 = head2.next
return True

23#

反转链表。

因为倒着做,前面用过很多次了。

class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
pre = None
cur = head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre

22#

相交链表。

没想到题解这种思路,相当于两条路都走两遍的话肯定能找到。

class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
p = headA
q = headB
while p is not q:
p = p.next if p else headB
q = q.next if q else headA
return p

21#

搜索二维矩阵II。

矩阵满足每行递增,每列递增,搜有无目标值。

每次看右上角能杀掉一行或一列。

class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
n, m = len(matrix), len(matrix[0])
i, j = 0, m - 1
while i <= n - 1 and j >= 0:
if matrix[i][j] == target:
return True
if matrix[i][j] > target:
j -= 1
if matrix[i][j] < target:
i += 1
return False