链表理论基础
注意点
- 链表的定义
单链表
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
- 使用虚拟头节点
dummy
,可以用一种统一的方式处理所有节点。
注意对链表节点操作要找到 要处理的节点的前一个结点。
ListNode dummy = new ListNode(-1, head);
ListNode cur = dummy;
反转链表
双指针法
首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。
从前往后遍历链表同时改变指针指向,注意要用temp指针保存cur.next。
两两交换链表中的节点
正常模拟,注意:
- 当对头结点(没有前一个指针指向头结点)需要单独处理时,使用虚拟头节点
- 对链表遍历过程中,可以根据需要设置临时节点,有时一个,有时两个....
删除链表的倒数第 N 个结点
快慢指针
要点:
- 使用虚拟头结点,这样方便处理删除实际头结点的逻辑
- fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作)
链表相交
题目数据 保证 整个链式结构中不存在环。
很简单,先求长度差,长的表先走差值个节点,然后两表一起走,直到节点相等
环形链表II
偏数学一些,
1.先通过快慢指针找到相遇节点meet,(从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。)相交点一定在环内;
2.head 和 meet同步走,到相遇时即为入口节点。