文章目录
链表含义
重点注意链表中以下几个语句的用法:
- cur->next = other 表示把当前指针的下一个指向other
- cur = cur->next 表示移动,把cur移动到cur的下一个
- 当一个指针cur = head时,如果移动cur = cur->next则head不会移动,如果改变cur->next = node 则head跟cur一样会执行改变改变链表结构
- 当要移动游标节点时,先定一个固定头节点或者dummy节点,然后去移动游标节点
- 注意在将链表中的节点插入到前面时,要先断开再插入,防止循环指向
进位操作
-
- 两数相加
-
- 分隔链表
快慢指针
找环和中间节点模板:快指针走两步,慢指针走一步
ListNode * fast = head;
ListNode * slow = head;
//有环时候相遇就退出循环
while(fast != nullptr && fast->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
//如果有环,则快慢指针相等,这里加判断
}
-
- 链表的中间结点
-
- 环形链表
-
- 环形链表 II
模板:快指针先走K步然后快慢指针一起走
- 倒数第K个节点(剑指22,面试题0202) 快慢指针一次遍历
两个指针走自己的然后走对方的,相遇即相交处
-
- 相交链表
删除节点
删除节点重点是定义一个前序节点(虚拟头节点)pre,开始的时候记录哑节点位置
-
- 移除链表元素 (删除节点重点是定义一个前序节点(虚拟头节点)pre,开始的时候记录哑节点位置)
-
- 删除链表的倒数第N个节点(快慢指针基础上,创建哑节点和临时节点)
-
- 删除排序链表中的重复元素
-
- 删除排序链表中的重复元素 II
反转链表
需要三个指针,一个临时指针
ListNode* pre = nullptr;//这里创建一个空节点,而不是哑节点指向头
ListNode* cur = head;
while(cur != nullptr) {
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
-
- 反转链表
-
- 反转链表 II (创建哑节点)
-
- 回文链表
k个一组反转链表
反转链表前N个节点
pair<ListNode *, ListNode*> reverseN(ListNode *head, int n)
{
ListNode *pre = nullptr;
ListNode *cur = head;
int count = 0;
while(count < n) {
ListNode * next = cur->next;
cur->next = pre;
//移动
pre = cur;
cur = next;
count++;
}
head->next = cur;
return {
pre, head};
}
-
- K 个一组翻转链表
-
- 两两交换链表中的节点
合并链表(归并)
归并模板:前序拆解,后序组装
ListNode* mergeTemplate(vector<ListNode*>& lists, int l, int r) {
if(l >= r) return lists[l];
int mid = (l + r) / 2;
//递归这里类似于二叉树前序遍历,实际上是先把列表拆分成一块一块
ListNode* l1 = mergeTemplate(lists, l, mid);
ListNode* l2 = mergeTemplate(lists, mid+1, r);
//后序遍历,分到不能再分,将链表合并向上返回
return mergeTwoLists(l1,l2);
}
-
- 合并两个有序链表
-
- 合并K个升序链表(顺序,归并)重点(归并写法)
-
- 排序链表(归并,同23)
-
- 复制带随机指针的链表
-
- 对链表进行插入排序
二叉树转换链表
-
- 二叉树展开为链表