返回
揭秘解题套路:手把手教你攻克单链表六大难题
闲谈
2024-01-31 03:05:41
破解单链表六大解题套路:助你轻松驾驭各种难题
身为一名程序员,你是否曾被单链表的复杂问题困扰不已?比如合并有序链表、寻找环形链表、确定链表中点等。这些难题看似棘手,但掌握正确的解题套路,它们将迎刃而解。
1. 合并两个有序链表
想象你有一对井然有序的链表,你需要将它们合并成一个新的有序链表。套路很简单:
- 定义两个指针,分别指向两个链表的头部。
- 比较两个指针所指向节点的值。
- 如果值相等,合并节点,并将指针指向下一个节点。
- 如果值不等,将较小节点合并到较大节点后,并将较小节点的指针指向较大节点的下一个节点。
- 重复以上步骤,直到两个指针都指向空节点。
代码示例:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode(0)
curr = dummy
while l1 and l2:
if l1.val < l2.val:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
curr = curr.next
curr.next = l1 or l2
return dummy.next
2. 合并 K 个升序链表
这是一个合并有序链表的高级版,你需要将 K 个有序链表合并为一个。套路与上一条相似:
- 定义一个虚拟节点,并将 K 个链表的头部指向它。
- 比较虚拟节点的下一个节点的值。
- 如果值相等,合并节点,并将虚拟节点的下一个节点指向下一个节点。
- 如果值不等,将较小节点合并到较大节点后,并将较小节点的指针指向较大节点的下一个节点。
- 重复以上步骤,直到虚拟节点的下一个节点指向空节点。
代码示例:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
dummy = ListNode(0)
curr = dummy
heap = []
for node in lists:
if node:
heapq.heappush(heap, (node.val, node))
while heap:
val, node = heapq.heappop(heap)
curr.next = node
curr = curr.next
if node.next:
heapq.heappush(heap, (node.next.val, node.next))
return dummy.next
3. 寻找环形链表
环形链表是指链表中的某个节点指向链表中的另一个节点,形成一个环。套路如下:
- 使用快慢指针。
- 快指针每次移动两个节点,慢指针每次移动一个节点。
- 如果快指针和慢指针相遇,则链表中存在环。
代码示例:
def hasCycle(self, head: ListNode) -> bool:
if not head or not head.next:
return False
slow = head
fast = head.next
while slow != fast:
if not fast or not fast.next:
return False
slow = slow.next
fast = fast.next.next
return True
4. 寻找环形链表 II
这是寻找环形链表的进阶版,你需要找到环的入口节点。套路如下:
- 使用两个指针,一个指向链表的头部,另一个指向相遇的两个节点。
- 将指向头部 的指针每次移动一步,将指向相遇节点的指针每次移动两步。
- 当两个指针相遇时,相遇的节点就是环的入口节点。
代码示例:
def detectCycle(self, head: ListNode) -> ListNode:
if not head or not head.next:
return None
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
if slow != fast:
return None
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
5. 寻找链表的中点
你需要找到链表中点的节点。套路如下:
- 使用快慢指针。
- 快指针每次移动两个节点,慢指针每次移动一个节点。
- 当快指针到达链表的尾部时,慢指针刚好到达链表的中点。
代码示例:
def middleNode(self, head: ListNode) -> ListNode:
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
6. 反转链表
你需要将链表中的所有节点的顺序颠倒过来。套路如下:
- 使用三个指针,分别指向当前节点、前一个节点和下一个节点。
- 将当前节点的下一个节点指向前一个节点,并将前一个节点指向当前节点。
- 重复以上步骤,直到当前节点指向空节点。
代码示例:
def reverseList(self, head: ListNode) -> ListNode:
prev = None
curr = head
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
return prev
总结
掌握这六大解题套路,你将能够轻松应对各种单链表问题。
常见问题解答
-
为什么使用快慢指针来查找环形链表?
- 快慢指针可以帮助确定链表中是否存在环,因为如果存在环,快指针最终将追上慢指针。
-
如何找到环形链表的入口节点?
- 在发现环形链表后,可以将一个指针指向头部,另一个指针指向相遇的节点,然后以相同的速度移动两个指针,相遇的节点就是入口节点。
-
为什么反转链表需要三个指针?
- 三个指针用于跟踪当前节点、前一个节点和下一个节点,以正确更新链表的指针。
-
能否只使用一个指针来反转链表?
- 不可以,因为只使用一个指针无法存储前一个节点的信息。
-
如何用单链表实现队列?
- 可以使用两个指针,一个指向队头,一个指向队尾,并通过尾部指针插入元素,通过头部指针删除元素。