文章目录
- 前言
- 思考问题:把分开的节点连在一起
- 结合原题:使用[迭代]解决卡点
- 引入新指针
- 边界条件
- 代码
- 反转的逻辑
- 代码(完整答案)
- 结合原题:使用[递归]解决卡点
- 完整代码
- 问题的子问题
- 当前层要干什么
- 递归出口
前言
这道题可以拆成几个小点去理解,本篇博文快速记录一下。有迭代和递归两种解法。迭代的解法空间复杂度更优秀,递归的思想更巧妙。这里主要总结下迭代的解法。并简要理解下递归的解法。
- LeetCode 206. 反转链表
思考问题:把分开的节点连在一起
- 以下是分开的节点(假定以下四个节点都能以数组的形式按序访问)
- 用一个指针遍历既可以连在一起
- 最终的结果
结合原题:使用[迭代]解决卡点
题目用链表组织原始节点,也就是四个节点只能使用向后遍历的方式按序访问。
- cur指针可以从头遍历到尾,结合上文尝试用一个指针去完成需求,会遇到难题
引入新指针
新指针的使命是:在原始链表中记住cur 的下一个节点,在指针断裂后,依旧能让cur继续遍历。
- 根据官方题解,把指针的名字改一下(思想是统一的)
边界条件
-
开始
-
结尾
代码
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
// 暂时忽略链表反转的逻辑
cur = cur.next; // 这句后续要改造
}
return pre;
}
反转的逻辑
- 结果:加入第一个节点(第一个要加入的是NULL),下一轮开始加入cur指向的节点
代码(完整答案)
public ListNode reverseList(ListNode head) {
if (head == null) {
return head;
}
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
// 1. 记住cur的下一个节点, 避免指针断裂后找不到后续元素
ListNode next = cur.next;
// 2. cur 指针指向pre,同时断开原链表的方向
cur.next = pre;
// 3. pre 这一轮的使命完成了, 下一轮要处理的pre就是当前的cur所指向的元素
pre = cur;
// 4. 同理, 下一轮要处理的cur就是刚刚保留起来防止找不到的节点 next
cur = next;
}
return pre;
}
结合原题:使用[递归]解决卡点
递归掌握的还是不够好,参考人家的题解,以后加以复习
参考leetCode的题解的图去观察回溯的过程
思考三个问题
- 这个问题的子问题是什么。
- 当前层要干什么事情。
- 递归出口。
完整代码
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}
问题的子问题
node1 -> node2 -> node3 -> node4 反转整个链表可以视为以下过程的组合:
-
1 ~ 3 节点 与 4 节点 反转: node1 -> node2 -> node3 ->[node4]
-
1 ~ 2 节点 与 3 节点 反转:node1 -> node2 -> [node3 <- node4]
-
1 节点 与 2 节点的反转: node1 -> [node2 <- node3 <- node4]
完成后: [node1 <- node2 <- node3 <- node4]
public ListNode reverseList(ListNode head) {
// 这个模型, 就是让程序递归到最深处的节点(遇到最后一个节点node4,再回到node3), 此时 head 为 node3
ListNode newHead = reverseList(head.next);
// 从 node4 回溯到 node1, 以下代码就是当前层要处理的问题
head.next.next = head;
head.next = null;
return newHead;
}
当前层要干什么
// head.next 就是 node4, head 就是node3
head.next.next = head;
head.next = null;
递归出口
if (head == null || head.next == null) {
return head;
}