< 思维导图 >

链表全部逆序 (★)

• LeetCode 206. Reverse Linked List.cpp
``````#include <stdio.h>

struct ListNode{
int val; // 数据域
ListNode *next; // 指针域
// 构造函数
ListNode(int x) : val(x), next(NULL) { }
};
class Solution{
public:
}
}
};
int main(){
ListNode a(11),b(22),c(33),d(44),e(55);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
Solution s;
printf("Before reverse:\n");
}
printf("After reverse:\n");
}
return 0;
}
``````

链表部分逆序 (★★)

• LeetCode 92. Reverse Linked List II.cpp
``````#include <stdio.h>

struct ListNode{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL){ }
};
class Solution{
public:
ListNode* reverseBetween(ListNode* head, int m, int n){
int len = n - m + 1;
}
len--;
}
}
};
int main(){
ListNode a(1),b(2),c(3),d(4),e(5);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
Solution s;
ListNode *head = s.reverseBetween(&a, 2, 4);
}
return 0;
}
``````

链表求交点 (★)

• 思路一，set 法求交集
• LeetCode 160.Intersection of Two LinkedLists (solve1).cpp
``````#include <stdio.h>

struct ListNode{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL){ }
};
// STL set 的使用
#include <set>

class Solution{
public:
// 求两链表交点 ( 链表 A头指针，链表 B头指针 )
// 查找集合 node_set
std::set<ListNode*> node_set;
// 各个节点都插入 node_set
// 遍历链表 A
}
// 当找到 node_set 的节点时
}
// 遍历链表 B
}
// 若没有交点，返回 NULL
return NULL;
}
};

int main(){
ListNode a1(1), a2(2);
ListNode b1(3), b2(4), b3(5);
ListNode c1(6), c2(7), c3(8);
a1.next = &a2; a2.next = &c1;
c1.next = &c2; c2.next = &c3;
b1.next = &b2; b2.next = &b3; b3.next = &c1;
// a1: 1，2，6，7，8
// b1: 3，4，5，6，7，8
Solution s;
ListNode *result = s.Solve(&a1, &b1);
printf("%d\n", result->val);
return 0;
}
``````
• 思路二，空间复杂度法
• LeetCode 160.Intersection of Two LinkedLists (solve2).cpp
``````#include <stdio.h>

struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
// 得到链表长度
int len = 0;
len++;
}
return len;
}

ListNode *forward_long_list(int long_len, int short_len, ListNode *head){
// x 为链表长度之差
int x = long_len - short_len;
// 将长链表头向前移动 x
x--;
}
}

class Solution {
public:
// A, B 链表长度
if (lenA > lenB){
}
else{
}
}
}
// 若没有交点，返回 NULL
return NULL;
}
};

int main(){
ListNode a1(1), a2(2);
ListNode b1(3), b2(4), b3(5);
ListNode c1(6), c2(7), c3(8);
a1.next = &a2; a2.next = &c1;
c1.next = &c2; c2.next = &c3;
b1.next = &b2; b2.next = &b3; b3.next = &c1;
// a1: 1，2，6，7，8
// b1: 3，4，5，6，7，8
Solution s;
ListNode *result = s.Solve(&a1, &b1);
printf("%d\n", result->val);
return 0;
}
``````

链表求环 (★★)

• 思路一，set 法求起始点
• LeetCode 142. Linked List Cycle II (solve1).cpp
``````#include <stdio.h>
#include <set>

struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
// 设置 set
std::set <ListNode *> A;
// 如果再次出现，且不是末尾
}
// 遍历一遍后 set：123456
}
return NULL;
}
};

int main(){
ListNode a(1),b(2),c(3),d(4),e(5),f(6);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
f.next = &c;
Solution s;
ListNode *node = s.Solve(&a);
if (node){
printf("有链表环，起始点：%d\n", node->val);
}
else{
printf("NULL\n");
}
return 0;
}
``````
• 思路二，快慢指针法
• LeetCode 142. Linked List Cycle II (solve2).cpp
``````#include <stdio.h>

struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
ListNode *meet = NULL;
while(fast){
slow = slow->next;
fast = fast->next;
fast = fast->next;
// 若相遇，返回 meet = fast
if (fast == slow){
meet = fast;
break;
}
}
// 若不相遇，返回 NULL
if (meet == NULL){
return NULL;
}
}
meet = meet->next;
}
return NULL;
}
};

int main(){
ListNode a(1),b(2),c(3),d(4),e(5),f(6),g(7);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
f.next = &g;
g.next = &c;
Solution s;
ListNode *node = s.Solve(&a);
if (node){
printf("有链表环，起始点：%d\n", node->val);
}
else{
printf("NULL\n");
}
return 0;
}
``````

链表划分 (★★)

• 临时结点头法
• LeetCode 86.Partition List.cpp
``````#include <stdio.h>

struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* Solve(ListNode* head, int x) {
ListNode *more = &more_head; // 两个临时指针
// 若小于 x，节点插入 less 后
}
// 若大于 x，节点插入 more 后
else {
}
}
// 连接 less链表尾 more链表头
more->next = NULL;
}
};

int main(){
ListNode a(1),b(4),c(3),d(2),e(5),f(2);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
Solution s;
}
return 0;
}
``````

复杂链表的复制 (★★★)

• LeetCode 138.Copy List with Random Pointer.cpp
``````#include <stdio.h>

struct RandomListNode {
int label; // label 为节点
RandomListNode *next, *random; // random 为随机指针
RandomListNode(int x) : label(x), next(NULL), random(NULL) { }
};

#include <map> // STL map 头文件
#include <vector>

class Solution {
public:
std::map <RandomListNode *, int> node_map; // 地址到节点的 map
std::vector<RandomListNode *> node_vec; // 存储节点的 vector
int i = 0;
// 第一次遍历
while (ptr){
// 新链表的节点存储到 node_vec
node_vec.push_back(new RandomListNode(ptr->label));
// 原链表地址到节点的 node_map
node_map[ptr] = i;
ptr = ptr->next;
i++;
}
node_vec.push_back(0);
i = 0;
// 第二次遍历
while(ptr){
// 连接新链表的 next 指针
node_vec[i]->next = node_vec[i+1];
// 若 ptr->random 不为空
if (ptr->random){
// 根据 node_map，原链表 random 指针指向 id
int id = node_map[ptr->random];
// 连接新链表的 random 指针
node_vec[i]->random = node_vec[id];
}
ptr = ptr->next;
i++;
}
// 返回连接后的链表
return node_vec[0];
}
};

int main(){
RandomListNode a(1),b(2),c(3),d(4),e(5);
a.next = &b;  b.next = &c;  c.next = &d;  d.next = &e;
// d->random 为空
a.random = &c;  b.random = &d;  c.random = &c;  e.random = &d;
Solution s;
// 复制 random 随机指向后的链表
}
else{
printf("random = NULL\n");
}
}
return 0;
}
``````

2 个排序链表归并 (★)

• LeetCode 21.Merge Two Sorted Lists.cpp
``````#include <stdio.h>

struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
// 若两节点都不为空
while (l1 && l2){
// 将 pre 与较小的节点连接
if (l1->val < l2->val){
pre->next = l1;
l1 = l1->next;
}
else{
pre->next = l2;
l2 = l2->next;
}
// pre 指向新节点
pre = pre->next;
}
// 如果 l1 有余，接到 pre 后
if (l1){
pre->next = l1;
}
// 如果 l2 有余，接到 pre 后
if (l2){
pre->next = l2;
}
}
};

int main(){
ListNode a(1),b(4),c(6);
ListNode d(0),e(5),f(7);
a.next = &b;  b.next = &c;
d.next = &e;  e.next = &f;
Solution s;
// 合并排序两个链表
}
return 0;
}
``````

K 个排序链表归并 (★★★)

• 思路一，暴力合并
• 思路二，排序后相连
• LeetCode 23.Merge k Sorted Lists(solve1).cpp
``````#include <stdio.h>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

#include <vector>
#include <algorithm>
// 若 a 节点数值小于 b，则返回 true
bool cmp(const ListNode *a, const ListNode *b){
return a->val < b->val;
}
class Solution {
public:
ListNode* mergeKLists(std::vector<ListNode*>& lists) {
std::vector<ListNode *> node_vec;
// 遍历所有链表
for (int i = 0; i < lists.size(); i++){
// 遍历当前链表所有节点，并存入 node_vec
}
}
// 根据节点数值进行排序
std::sort(node_vec.begin(), node_vec.end(), cmp);
// 连接所有排序后的节点
for (int i = 1; i < node_vec.size(); i++){
node_vec[i-1]->next = node_vec[i];
}
node_vec[node_vec.size()-1]->next = NULL;
return node_vec[0];
}
};
int main(){
// 定义三个链表
ListNode a(1),b(4),c(6);
ListNode d(0),e(5),f(7);
ListNode g(2),h(3);
a.next = &b;  b.next = &c;
d.next = &e;  e.next = &f;
g.next = &h;
// 将三个链表头存入 lists
std::vector<ListNode *> lists;
lists.push_back(&a);
lists.push_back(&d);
lists.push_back(&g);
Solution s;
// 输出所有链表及归并结果
printf("链表一 ：");
}

printf("\n链表二 ：");
}
printf("\n链表三 ：");
}
printf("\n归并后 ：");
}
return 0;
}
``````
• 思路三，分治后相连
• LeetCode 23.Merge k Sorted Lists(solve2).cpp
``````#include <stdio.h>
struct ListNode {
int val;
ListNode *next;
ListNode (int x) : val(x), next(NULL) {}
};

#include <vector>
class Solution {
public:
// 两个链表排序归并
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
while (l1 && l2){
if (l1->val < l2->val){
pre->next = l1;
l1 = l1->next;
}
else{
pre->next = l2;
l2 = l2->next;
}
pre = pre->next;
}
if (l1){
pre->next = l1;
}
if (l2){
pre->next = l2;
}
}
// 分治处理
ListNode* mergeKLists(std::vector<ListNode*>& lists) {
// 如果一个链表，不做处理
if (lists.size() == 1){
return lists[0];
}
// 如果两个链表，排序归并
if (lists.size() == 2){
return mergeTwoLists(lists[0], lists[1]);
}
// 拆分 lists 为 list1 、list2
int mid = lists.size() / 2;
std::vector<ListNode*> list1;
std::vector<ListNode*> list2;
for (int i = 0; i < mid; i++){
list1.push_back(lists[i]);
}
for (int i = mid; i < lists.size(); i++){
list2.push_back(lists[i]);
}
// list1 的一个链表，不做处理
ListNode *l1 = mergeKLists(list1);
// list2 的两个链表，排序归并
ListNode *l2 = mergeKLists(list2);
// list1、list2 两链表排序归并
return mergeTwoLists(l1, l2);
}
};

int main(){
// 定义三个链表
ListNode a(1),b(4),c(6);
ListNode d(0),e(5),f(7);
ListNode g(2),h(3);
a.next = &b;  b.next = &c;
d.next = &e;  e.next = &f;
g.next = &h;
// 将三个链表头存入 lists
std::vector<ListNode *> lists;
lists.push_back(&a);
lists.push_back(&d);
lists.push_back(&g);
Solution s;