链表

链表

c语言动态内存管理中

链表结构无处不在

有fast bin这种单向链表

也有unsorted bin这种双向链表

我应该还是蛮熟悉的…

重点在于对指针的理解

做题过程中呢发现

核心算法是

双指针

那么

启动!

160.相交链表

如图

双指针好吧

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA || !headB) return nullptr;
ListNode* p1 = headA;
ListNode* p2 = headB; //双指针
while(p1 != p2){
p1 = (p1 ? p1->next : headB);
p2 = (p2 ? p2->next : headA);
}
return p1; //相交节点 or nullptr(p2)
}
};

206.反转链表

如图

解法:

reverse!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* cur = head;

while(cur){
ListNode* tmp = cur->next; //保存节点
cur->next = prev;
prev = cur;
cur = tmp;
}
return prev;
}
};

234.回文链表

如图

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(!head || !head->next) return true;
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
}

ListNode* prev = nullptr;
while(slow){
ListNode* next = slow->next;
slow->next = prev;
prev = slow;
slow = next; //反转链表
}
ListNode* left = head;
ListNode* right = prev;
while(right){
if(left->val != right->val){
return false;
}
left = left->next;
right = right->next;
}
return true;
}
};

141.环形链表

如图

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head || !head->next) return false;
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
if(slow == fast) return true;
}
return false;
}
};

142.环形链表II

如图

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head || !head->next) return nullptr;
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
if(slow == fast) break;
}
if(!fast || !fast->next) return nullptr;
slow = head;
while(slow != fast){
slow = slow->next; //思考...
fast = fast->next;
}
return slow;
}
};

21.合并两个有序链表

如图

解:

双指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode dummy(0);
ListNode* cur = &dummy;
while(list1 && 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 ? list1 : list2;
return dummy.next;
}
};

2.两数相加

如图

链表逐位相加并维护进位,用dummy head简化边界处理线性时间构造结果链表~

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* cur = &dummy;
int carry = 0;
while(l1 || l2 || carry) {
int sum = carry;
if(l1) {
sum += l1->val;
l1 = l1->next;
}
if(l2) {
sum += l2->val;
l2 = l2->next;
}
carry = sum / 10;
cur->next = new ListNode(sum % 10);
cur = cur->next;
}
return dummy.next;
}
};

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

还是通过虚拟头结点配合快慢指针保持固定间距,在一次线性遍历中定位并删除倒数第 n 个节点,统一处理头结点等边界情况~

如图

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(0);
dummy.next = head;
ListNode* fast = &dummy;
ListNode* slow = &dummy;
for(int i = 0; i <= n; i++) {
fast = fast->next;
}
while(fast) {
fast = fast->next;
slow = slow->next;
}
ListNode* del = slow->next;
slow->next = del->next;
delete del;

return dummy.next;
}
};

24.两两交换链表中的节点

依旧通过引入虚拟头结点并维护前驱指针,每次对相邻两个节点进行指针重连,在一次线性遍历中完成成对交换并统一处理头结点变化~

如图

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode dummy(0);
dummy.next = head;
ListNode* prev = &dummy;

while(prev->next && prev->next->next) {
ListNode* a = prev->next;
ListNode* b = a->next;

a->next = b->next;
b->next = a;
prev->next = b;

prev = a;
}
return dummy.next;
}
};

25.K个一组翻转链表

如图

解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode dummy(0);
dummy.next = head;
ListNode* prev = &dummy;
while(true) {
// 找 k 个节点
ListNode* node = prev;
for(int i = 0; i < k && node; i++) {
node = node->next;
}
if(!node) break;

// 记录下一组
ListNode* curr = prev->next;
ListNode* temp = curr->next;

// 翻转
for(int i = 1; i < k; i++) {
curr->next = temp->next;
temp->next = prev->next;
prev->next = temp;
temp = curr->next;
}
// prev 移动
prev = curr;
}
return dummy.next;
}
};

138.随机链表的复制

如图

解法1:

哈希表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;

Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/

class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head) return nullptr;
unordered_map<Node*, Node*> mp;

Node* cur = head;
while(cur) {
mp[cur] = new Node(cur->val);
cur = cur->next;
}
cur = head;
while(cur) {
mp[cur]->next = mp[cur->next];
mp[cur]->random = mp[cur->random];
cur = cur->next;
}

return mp[head];
}
};

解法2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;

Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/

class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head) return nullptr;
Node* cur = head;

// 插入复制节点
while(cur) {
Node* copy = new Node(cur->val);
copy->next = cur->next;
cur->next = copy;
cur = copy->next;
}

// 设置 random
cur = head;
while(cur) {
if(cur->random) {
cur->next->random = cur->random->next;
}
cur = cur->next->next;
}

// 拆链表
cur = head;
Node* newHead = head->next;

while(cur) {
Node* copy = cur->next;
cur->next = copy->next;
if(copy->next) {
copy->next = copy->next->next;
}
cur = cur->next;
}

return newHead;
}
};

148.排序链表

如图

解:

归并排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* cur = &dummy;
while(l1 && l2) {
if(l1->val < l2->val) {
cur->next = l1;
l1 = l1->next;
}else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = l1 ? l1 : l2;

return dummy.next;
}
ListNode* sortList(ListNode* head) {
if(!head || !head->next) return head;
// 快慢双指针找中点
ListNode* slow = head;
ListNode* fast = head->next;
while(fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
ListNode* mid = slow->next;
slow->next = nullptr;

ListNode* left = sortList(head);
ListNode* right = sortList(mid);

return merge(left, right);
}
};

23.合并K个升序链表

如图

解:

小顶堆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
struct cmp {
bool operator()(ListNode* a, ListNode* b) {
return a->val > b->val; // 小顶堆
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, cmp> pq;

for(auto node : lists) {
if(node) pq.push(node);
}

ListNode dummy(0);
ListNode* cur = &dummy;

while(!pq.empty()) {
ListNode* node = pq.top();
pq.pop();

cur->next = node;
cur = cur->next;

if(node->next) {
pq.push(node->next);
}
}
return dummy.next;
}
};

146.LRU缓存

如图

解:

least recently used cache

哈希表 + 双向链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class LRUCache {
private:
struct Node {
int key;
int val;
Node* prev;
Node* next;

Node(int k,int v):key(k),val(v),prev(nullptr),next(nullptr){}
};

unordered_map<int,Node*> cache;
int capacity;

Node* head;
Node* tail;
public:
LRUCache(int capacity) {
this->capacity = capacity;

head = new Node(0,0);
tail = new Node(0,0);

head->next = tail;
tail->prev = head;
}

// 双向链表 remove
void remove(Node* node) {
node->prev->next = node->next;
node->next->prev = node->prev;
}

// 双向链表 insert
void insert(Node* node) {
node->next = head->next;
node->prev = head;

head->next->prev = node;
head->next = node;
}

// unordered_map 实现 O(1) get
int get(int key) {
// 没有找到直接返回
if(cache.count(key) == 0) {
return -1;
}
Node* node = cache[key];

// 找到 -> 更新 LRU 缓存
remove(node);
insert(node);

return node->val;
}

// 分类讨论 实现 put
void put(int key, int value) {
if(cache.count(key)) {
Node* node = cache[key];
node->val = value;

remove(node);
insert(node);
}else {
if(cache.size() == capacity) {
Node* node = tail->prev;
remove(node);
cache.erase(node->key);
}
Node* node = new Node(key,value);

cache[key] = node;

insert(node);
}
}
};

/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/

链表
https://roxy5201314.github.io/2026/01/19/链表/
作者
roxy
发布于
2026年1月19日
更新于
2026年3月9日
许可协议