1. 链表的常用技巧和操作
常用技巧:
- 链表的难点在于改变指针的指向 和时机 ,因此做链表类型的题时,画图模拟是非常必要的。
- 适当引入虚拟头节点,可以避免过多的分类讨论,降低复杂性的同时还有助于处理边界情况。
- 快慢双指针:常用于判断链表是否带环,找带环链表的入口,找倒数第n个节点......
- 大大方方定义变量 ,不要吝惜空间。如图,在定义
next变量后则可以忽略指针指向的先后顺序。

常用操作:
cpp
/**
* 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) {}
* };
*/
//1. 创建值为0的节点
//方式1:堆上分配(指针)
ListNode* newnode = new ListNode(0);
// 类型:ListNode*
// 生命周期:手动 delete 释放
// 用途:链表节点通常用这种方式
//方式2:栈上分配(对象)
ListNode head(0);
// 类型:ListNode
// 生命周期:作用域结束自动销毁
// 用途:临时对象或局部使用
//2. 尾插newnode(cur所在位置为尾节点)
cur->next = newnode;
cur = cur->next;
//3. 头插newnode(newhead为虚拟头节点)
cur = newhead->next;
newhead->next = newnode;
newnode->next = cur;
2. 例题分析
2.1 两数相加
解题思路:
模拟两数相加的过程。因为两个链表都是逆序存储数字的,即两个链表的个位数、⼗位数等都已经对应,可以直接相加。过程中需要注意是否产生进位:
- 过程中需要将进位和链表数字一同相加
- 相加结束后若还需进位则需要
new一个节点

cpp
class Solution {
public:
typedef ListNode Node;
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
Node* cur1 = l1;
Node* cur2 = l2;
Node* newhead = new Node(0);
Node* prev = newhead;
int next = 0;
while(cur1 || cur2)
{
int sum = next;
if(cur1)
{
sum += cur1->val;
cur1 = cur1->next;
}
if(cur2)
{
sum += cur2->val;
cur2 = cur2->next;
}
Node* tmp = new Node(sum % 10);
prev->next = tmp;
prev = tmp;
next = sum / 10;
}
if(next != 0)
{
Node* tmp = new Node(next);
prev->next = tmp;
}
Node* ret = newhead->next;
delete newhead;
return ret;
}
};
2.2 两两交换链表中的节点
解题思路:
模拟交换链表的过程,这里需要定义四个变量prev, c1, c2, next,循环交换直至链表结尾。注意在交换之后,对应指针的指向已经改变,更新指针时应以交换后的指针为准。

cpp
class Solution {
public:
typedef ListNode Node;
ListNode* swapPairs(ListNode* head)
{
if(!head || !head->next) return head;
Node* newhead = new Node(0);
Node* prev = newhead;
newhead->next = head;
Node* c1 = head;
Node* c2 = head->next;
Node* next = c2->next;
while(c1 && c2)
{
c1->next = next;
c2->next = c1;
prev->next = c2;
if(!next || !next->next)
{
break;
}
prev = c1;
c1 = next;
c2 = c1->next;
next = c2->next;
}
Node* ret = newhead->next;
delete newhead;
return ret;
}
};
2.3 重排链表
解题思路:
- 找中间节点(快慢双指针)
- 中间部分往后的节点逆序(双指针 / 头插)
- 合并两个链表(双指针)

cpp
class Solution {
public:
typedef ListNode Node;
ListNode* swapPairs(ListNode* head)
{
if(!head || !head->next) return head;
Node* newhead = new Node(0);
Node* prev = newhead;
newhead->next = head;
Node* c1 = head;
Node* c2 = head->next;
Node* next = c2->next;
while(c1 && c2)
{
c1->next = next;
c2->next = c1;
prev->next = c2;
if(!next || !next->next)
{
break;
}
prev = c1;
c1 = next;
c2 = c1->next;
next = c2->next;
}
Node* ret = newhead->next;
delete newhead;
return ret;
}
};
// 本期内容就到这里啦,如果对你有帮助,请三连支持!我是青云,我们下期见^_~