链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
单链表
双链表
循环链表(约瑟夫环)
分布:散乱
链表结点的定义
// 单链表
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数
};
链表的增添和删除都是O(1)操作,也不会影响到其他节点
删除第五个节点,需要从头节点查找到第四个节点通过next指针进行删除操作,查找的时间复杂度是O(n)
链表感觉是高频面试题(自我感觉的)
分割线————————————————————————————————————
203.移除链表元素
题目描述:给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点
思考:删除节点并不是移除这个节点而是跳过这个节点直接指向下一个节点(头节点直接往下移成为一个新的头节点)
注意:c++需要手动释放被删除节点的内存
空指针错误:current不能为空且current-next也不能为空
值得注意的两点:1.循环是whlie还是if? 2.current的节点是head还是head—next?
借用一下卡哥的图:
current-next=current-
统一的方法:虚拟头节点
思路:定义一个节点指向head
ps:卡子哥的板书有点费眼睛,但是讲的很详细很清楚,家人们建议冲
dummy head才是新链表里的头节点(注意return的内容)
分割线————————————————————————————————————————
707.设计链表(经典永流传)
这道题目设计链表的五个接口:
- 获取链表第index个节点的数值------1
- 在链表的最前面插入一个节点-------2
- 在链表的最后面插入一个节点-------3
- 在链表第index个节点前面插入一个节点-------4
- 删除链表的第index个节点------------5
可以说这五个接口,已经覆盖了链表的常见操作,是练习链表操作非常好的一道题目
1.遍历链表的基本操作:定义指针current操作,指向头节点(不能直接操作头节点,容易使头结点的值发生改变)考虑极端情况:是否出现类似于空指针异常的情况或者遍历的不是第零个节点的情况
易错点:赋值不清楚/n的值不清楚
2.步骤:(注意有坑)
(1)先定义一个新的节点
(2)虚拟头节点指向新节点
(3)新节点指向头节点(无法指向头节点,head值无法获取)
正确步骤:
(1)先定义一个新的节点
(2)新节点指向头节点
(3)虚拟头节点指向新节点
3.当前遍历节点一定要指向尾部节点
停止遍历的的条件:current-next=null
4.一定要明确被插入节点(current—next)前一个节点(current)的指针,才能进行插入操作
(把n=0这种特殊情况带入分析更容易理解和分析)
5.合法性判断
第n个点是current-next
current-next=current-next-next
分割线————————————————————————————————————————
206.反转链表(笔试常考题,刚帮同学搜过)(基础数据结构操作的考察典型)
题目描述:给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
双指针:先移动pre,后移动current(着重掌握)
递归:(一一对应)