1. 链表反转
来源:Leetcode 206
方法一:迭代法(头节点插入法)
思路:创建一个节点dummy,总是用来标识一个新的链表的头节点,把源链表每一次循环脱落的节点,添加到dummy.Next中,最后新建的链表就是反转后的链表
方法二:迭代法-就地反转
思路:把当前节点的下一个节点插入到dummy的下一个节点,就地反转
2. 查找链表中间节点
来源:Leetcode 876
方法:快慢指针法
思路:设置两个指针slow,fast,分别标识快慢指针,每一次slow前进一个节点,fast都将双倍速度前进。则fast到链表末尾时,slow处于中间位置
3. 查找链表倒数第 k 个结点
来源:Leetcode 19
方法:间隔指针法
思路:设置指针ahead,rear,分别标识处于前方和后方的指针,两者间隔k,故当ahead到达链表末尾,rear处于K节点位置,删除rear即可
4. 逆序打印链表
来源:牛客网-《剑指Offer》第3题
名称:从尾到头打印链表
题目内容:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList
方法:递归
思路:简单的递归思想,直接深入到链表末尾,然后输出
5. 判断一个链表是否有环
来源:Leetcode 141
方法一:map映射法
思路:将链表节点的地址作为键名,写入map,每一次判断键名是否存在,若存在,则必定在该点闭合成环
方法一:快慢指针法
思路:将链表节点的地址作为键名,写入map,每一次判断键名是否存在,若存在,则必定在该点闭合成环
6. 相交链表
来源:Leetcode 160
方法一:map映射
思路:定义类型 map[*ListNode]int 键名存储节点的地址,第一次循环将headA的节点地址写入map中,第二次遍历headB时,直接判断map中是否存在 节点地址,存在则输出。
复杂度:O(n) 时间复杂度,O(n) 空间复杂度
7. 合并两个有序链表
来源:Leetcode 21
方法一:递归合并
思路:新建一个节点dummy用来标识某一个最小的链表头,每一次递归新生成的dummy的 Next 都等于再次递归生成的dummy
方法二:循环合并
思路:定义一个浮动节点dummy来指定每一次l1和l2比较后返回的节点,定义一个head节点标识dummy浮动的头部,每次都将dummy.Next指向l1和l2比较后的小者,后浮动dummy指向下一个节点,依次循环
8. 请判断一个链表是否为回文链表
来源:Leetcode 234 《回文链表》
方法一:container/list模拟栈操作
思路:获取链表长度,链表前半部分入栈,后半部分与出栈元素比较
复杂度:O(n) 时间复杂度,O(n) 空间复杂度
方法二:快慢双指针+链表反转
思路:用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题。需要用到双指针+链表反转,反正我们上面已经知道了如何反转链表,和利用快慢指针进行链表操作。将慢指针指向链表中央,往后的链表节点反转,再从头开始,比对链表头节点和中央往后的节点。
方法三:数组
思路:将所有节点值压入数组,比较索引i与len()-1-i的大小
9. 删除排序链表中的重复元素
来源:Leetcode 83
方法:前后比较法
思路:定义一个间隔指针pre指向当前操作节点的前面