前言
前言:链表面试高频题。
文章目录
- 前言
- 一. 基础回顾
- 二. 高频考题
- 1. 例题
- 1)题目链接(LeetCode 206 反转链表)
- 2) 算法思路
- 3)源码剖析
- 4)时间复杂度
- 2. 习题
一. 基础回顾
参考上一讲: 04 |「链表」简析
结构:
1
1
1->
2
2
2->
3
3
3->NULL,链表是 指向型
结构 。
查找:随机访问的时间复杂度是
O
(
n
)
O(n)
O(n)。
增删:删除和插入元素的时间复杂度都是
O
(
1
)
O(1)
O(1) 。
头结点(head
):对于链表,给你一个链表的时候我们拿到的是头节点(head
) 。如果没有头结点证明整个链表为空 NULL
,如果已经有头结点证明链表不为空。
虚拟头结点(dummy
) :如果链表为空(null
),那么 访问 null.val 与 null.next 出错。为了避免这种情况,增加一个虚拟头结点(dummy
),其中 dummy
的值 (val
)常用 -1
表示,这样 dummy.next = null,避免直接访问空指针。
// 增加虚拟头节点的链表遍历
dummy; dumm->next = head; p = dummy;
while (p)
{
}
// 没有虚拟头结点的链表遍历
head;
while (head)
{
head = head->next;
}
二. 高频考题
1. 例题
1)题目链接(LeetCode 206 反转链表)
原题链接:反转链表(点击链接直达)
2) 算法思路
- 明确:修改几条边,修改哪几条边,注意是修改
n
条边; - 操作:将当前节点的
next
指针改为指向前一个节点(last
); - 维护:双链表可以通过
pre
指针访问前一个节点。针对单链表,没有pre
指针无法访问前一个节点(last
),需要新开一个变量维护前一个节点(last
); - 边界:针对头结点(
head
)没有前一个节点,创建last
并赋为NULL
;
3)源码剖析
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* last = nullptr; //(1)
ListNode* cur = head; //(2)
while (cur) //(3)
{
ListNode* next = cur->next; //(4)
cur->next = last; //(5)
last = cur; //(6)
cur = next; //(7)
}
return last; //(8)
}
};
- (1)/(2):初始化变量
last
和cur
,last
指向上一个节点,cur
指向当前节点; - (3):修改每条边,需要循环遍历访问每个节点;
- (4):修改一条边时,先保存当前节点(
cur
)的下一个节点(next
),防止丢失; - (5):修改一条边;
- (6)/(7):
last
和cur
分别向后移动一位; - (8):返回反转后链表的头结点。当
cur
停下时指向原链表的NULL
,此时last
指向反转后链表的头结点;
4)时间复杂度
O
(
n
)
O(n)
O(n)
2. 习题
LeetCode 92 反转链表II 原题链接
LeetCode 876 链表的中间节点 原题链接
LeetCode 234 回文链表 原题链接
LeetCode 160 相交链表 原题链接
LeetCode 141 环型链表 原题链接
LeetCode 142. 环形链表 II 原题链接