一 实现思路
1 思维层面
1 递归法:
- S1 明确递归函数语义
- S2 在语义基础上 画出 数据结构示意图(一般是分成 已处理部分 + 未处理部分)
- S3 对当前节点进行操作,从而使其符合函数功能定义
2 迭代法:
2.1 在解决链表问题时,应该培养"单节点职责"的思维模式
- 每次操作只关注 当前节点要做的事情,其他节点的处理留给下一次循环
2.2 画图辅助思考
原始链表: 1 -> 2 -> 3 -> null
第一步: null <- 1 2 -> 3 -> null
第二步: null <- 1 <- 2 3 -> null
第N步: null <- 1 <- 2 <- 3
2 参考实现
二 代码实现
方法1: 递归法 时间复杂度O(n) 空间复杂度 O(n)
// 返回 反转后的链表头节点
function reverseList(head) {
if (!head || !head.next) return head;
// 函数功能语义: 反转了以head为头节点的链表,并返回了反转后的新头节点 newHead
let newHead = reverseList(head.next);
// 注意此时head.next,还指向着 反转后的尾节点, 即 curHead--> newTail <--yyy <-- newHead
// 所以想要反转包含curHead的整个链表,通过newTail(即 head.next)就很简单了
// 这一句就相当于 const newTail = head.next; newTail.next = head;
head.next.next = head
// 让curHead的next断开指向newTail,从而避免循环链表
head.next = null;
// 返回 新的头结点即可
return newHead;
}
方法2: 迭代法 时间复杂度O(n) 空间复杂度 O(1)
function reverseList(head) {
let pre = null, cur = head
while (cur) {
const willNext = cur.next
// 修改当前指针指向前一个
cur.next = pre
// 移动pre和cur到下一个节点
pre = cur
cur = willNext
}
// 到最后pre指向的就是 原链表的最后一个节点
return pre
}