链表是指针操控的基本功,翻转、合并、检测环,面试必考
链表(Linked List)是一种线性数据结构,每个节点包含数据和指向下一个节点的指针。与数组不同,链表在内存中不连续存储,插入删除 O(1),但随机访问 O(n)。链表问题的核心是指针操作——正确地断开和重连指针。
dummy = ListNode(0, head),最后返回 dummy.next# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
题目描述:将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0)
cur = dummy
while list1 and list2:
if list1.val <= list2.val:
cur.next = list1
list1 = list1.next
else:
cur.next = list2
list2 = list2.next
cur = cur.next
cur.next = list1 if list1 else list2
return dummy.next
时间复杂度:O(n+m) — 每个节点访问一次
空间复杂度:O(1) — 只用指针,不创建新节点
题目描述:给你单链表的头节点 head,请你反转链表,并返回反转后的链表。
new_head = reverseList(head.next)head.next.next = headhead.next = Noneclass Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev = None
curr = head
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
return prev
时间复杂度:O(n) — 一次遍历
空间复杂度:O(1) — 只用三个指针
题目描述:给你一个单链表的头节点 head,请你判断该链表是否为回文链表。
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
# 1. 快慢指针找中点
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 2. 反转后半段
prev = None
curr = slow
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
# 3. 双指针比较
left, right = head, prev
while right:
if left.val != right.val:
return False
left = left.next
right = right.next
return True
时间复杂度:O(n) — 三次遍历(找中点+反转+比较)
空间复杂度:O(1) — 只用指针
链表问题有一些固定套路,掌握这些套路可以快速解决大部分链表题。
找两条链表的交点(LC 160):让两个指针分别遍历 A+B 和 B+A,它们一定在交点相遇。
def getIntersectionNode(headA, headB):
pA, pB = headA, headB
while pA != pB:
pA = pA.next if pA else headB
pB = pB.next if pB else headA
return pA
LC 142 环形链表 II:快慢指针找到相遇点后,一个指针从头部出发,另一个从相遇点出发,两者相遇即为环的入口。
def detectCycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
p = head
while p != slow:
p = p.next
slow = slow.next
return p
return None