---
tags: Summary
---
# 链表
### 定义
```python=
class ListNode:
def __init__(self, x, next=None):
self.val = x
self.next = next
```
---
**1. 环形链表**
检测链表中的环
[141. 环形链表](https://leetcode-cn.com/problems/linked-list-cycle/)
```
1 -> 2 -> 3 -> 4
| |
7 <- 6 <- 5
```
快慢指针,相撞即有环
```python=
def hasCycle(head: ListNode) -> bool:
slow = fast = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
return True
return False
```
---
**2. 环形链表 II**
检测链表中的环,并输出入环的第一个结点,无环返回 None
[142. 环形链表 II](https://leetcode-cn.com/problems/linked-list-cycle-ii/)
先快慢指针检测是否有环,然后将 ptr 放到 head,同时开始 ptr 和 slow,相撞的点即为入环点
证明:设入环点前长度为 a,slow 走过的路程为 a + b,fast 走过的路程为 a + n(b + c) + b(n 为圈数,b + c 为环长)
fast 的路程一定是 slow 的两倍,所以 a + n(b + c) + b = 2a + 2b
所以 a = (n - 1)(b + c) + c
```python=
def detectCycle(head: ListNode) -> ListNode or None:
slow = fast = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
ptr = head
while ptr != slow:
slow = slow.next
ptr = ptr.next
return ptr
return None
```
---
**3. 相交链表**
找到两个单链表相交的起始结点
[160. 相交链表](https://leetcode-cn.com/problems/intersection-of-two-linked-lists/)
```
1 -> 2 -> 3
|
4 -> 5 -> 6 -> 7
```
双指针,相遇
时间 O(n) 空间 O(1)
```python=
def getIntersectionNode(headA: ListNode, headB: ListNode) -> ListNode or None:
nodeA, nodeB = headA, headB
while nodeA != nodeB:
nodeA = nodeA.next if nodeA else headB
nodeB = nodeB.next if nodeB else headA
return nodeA
```
---
**4. 链表的中间结点**
找出单链表的中间结点
[876. 链表的中间结点](https://leetcode-cn.com/problems/middle-of-the-linked-list/)
```
1 -> 2 -> 3 -> 4 -> 5
|
```
快慢指针,快的到链表尾,慢的即在中点
```python=
def middleNode(head: ListNode) -> ListNode:
slow = fast = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
return slow
```
---
**5. 反转链表**
反转一个单链表
[206. 反转链表](https://leetcode-cn.com/problems/reverse-linked-list/)
双指针
```python=
def reverseList(head: ListNode) -> ListNode:
pre, curr = None, head
while curr:
curr.next, pre, curr = pre, curr, curr.next
return pre
```
---
**6. K 个一组反转链表**
困难
将一个链表每 k 个结点一组进行反转,返回反转后的链表
input: 1 -> 2 -> 3 -> 4 -> 5; k = 2
output: 2 -> 1 -> 4 -> 3 -> 5
时间 O(n) 空间 O(1)
```python=
def reverseKGroup(head: ListNode, k: int) -> ListNode:
def reverse(one_head: ListNode, one_tail: ListNode) -> (ListNode, ListNode):
pre, curr = None, one_head
while pre != one_tail:
curr.next, pre, curr = pre, curr, curr.next
return one_tail, one_head
pre = dummy = ListNode(0, next=head)
curr = head
while curr:
for _ in range(k - 1):
curr = curr.next
if curr is None:
return dummy.next
one_head, one_tail, curr = pre.next, curr, curr.next # 确定下一步要 reverse 的头尾
one_head, one_tail = reverse(one_head, one_tail) # reverse
pre.next, one_tail.next = one_head, curr # 连接
pre = one_tail # 把 pre 移动到下一次的位置
return dummy.next
```
---
**7. 合并两个有序链表**
input: 1 -> 2 -> 4; 1 -> 3 -> 4
output: 1 -> 1 -> 2 -> 3 -> 4 -> 4
```python=
def mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode:
n1 = dummy = ListNode(0, next=l1)
n2 = l2
while n1.next and n2:
if n1.next.val >= n2.val:
n1.next, n2 = n2, n1.next
n1 = n1.next
if n2:
n1.next = n2
return dummy.next
```
---
**8. 合并 K 个有序链表**
input: 1 -> 4 -> 5; 1 -> 3 -> 4; 2 -> 6
output: 1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6
```python=
def mergeKLists(lists: list) -> ListNode:
def merge2Lists(l1: ListNode, l2: ListNode) -> ListNode:
n1 = dummy = ListNode(0, next=l1)
n2 = l2
while n1.next and n2:
if n1.next.val >= n2.val:
n1.next, n2 = n2, n1.next
n1 = n1.next
if n2:
n1.next = n2
return dummy.next
def recur(ls: list) -> ListNode:
if len(ls) == 0:
return None
if len(ls) == 1:
return ls[0]
mid = len(ls) // 2
return merge2Lists(recur(ls[:mid]), recur(ls[mid:]))
return recur(lists)
```