链表的特点主要是存储地址分散,无索引
访问一个链表节点主要是通过头节点依次遍历
链表主要分为单链表,双链表,循环链表,当然用得最多的还是单链表
首先,链表算法题主要是遍历链表,遍历过程中最需要注意的点就是容易产生空指针异常
- 当链表某个节点listNode为空时,访问其值val或者访问下一节点就会产生空指针异常
所以在访问链表某节点的值或者下一节点时需要提前判断一下节点是否为空node != null
链表的结构
- 每个链表节点主要包含该节点的值,以及指向下一节点的指针
链表算法题除了掌握题目意思准确找到题目所需的链表节点并处理以外,还要着重考虑头尾节点,头节点和尾节点是链表题目中经常重点考察的内容
例如
1、相交链表,判断两链表的相交点,从相交点开始两链表后面的节点相同
解题思路:两链表相交前的节点数量分别为a,b,相交后的节点数量为c,首先定义两指针分别遍历两链表,再遍历另一链表相交前的节点,此时两指针遍历过的节点数量分别为a+b+c = c+b+a,所以此时两指针必定会在相交处相遇
2、判断链表中环的开始
解题思路:环即为循环链表,循环链表的头尾节点相同。定义快慢指针,慢指针以一个单位长度依次遍历链表,快指针以两个单位长度依次遍历链表,快链表每次比慢链表多走一步,当两指针相遇时,当前节点到环的开始节点的距离等于从头节点到环的开始节点(2a+2b = a+2b+c),所以此时快慢指针分别从当前节点和头节点以一个单位长度遍历,相遇时即为链表环的开始节点
最后再考虑一下环的开始节点为链表节点,只需要在快慢指针相遇后指向头节点的指针判断是否为当前节点即可
3、翻转链表
解题思路:遍历链表,深拷贝头节点生成一个新链表的头节点,遍历下一节点,深拷贝该节点后将该节点放于新链表头节点前面,并将头节点指针置于最新节点,依次遍历完原链表后返回新链表的头节点即为翻转后的链表
最后需要特别注意的就是头节点需要提前深拷贝再遍历,尾节点注意空指针问题
4、删除链表倒数第n个节点
解题思路:首先遍历一遍链表得到链表的节点数量即链表的长度,再通过链表长度和n得到需要删除的节点,这道题就特别需要注意头尾节点问题,将需要删除的节点分为可能为头节点,尾节点,以及中间节点,对于头节点的删除直接返回头节点下一节点即可,对于尾节点的删除需要将需要删除的上一节点next指针为null,对于普通节点则需要将需要删除的上一节点的next指向需要删除节点的下一节点,即为node.next = node.next.next,同时需要注意空指针问题,当这些问题都注意到了这道题自然就迎刃而解了
这道题就需要特别一下头尾节点,对于不同类型的节点需要有不同的处理方式
总结:
- 链表的特点不连续无索引
- 链表问题特别注意空指针问题
- 链表头节点尾节点的特殊处理
- 循环链表的头尾节点相同