每天学习一点算法 2025/12/10
题目:反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
-
第一种方法把所有的节点都压入栈中,然后弹栈得到反转后的链表
typescriptfunction reverseList(head: ListNode | null): ListNode | null { if (head === null || head.next === null) return head const stack: ListNode[] = [] // 遍历链表所有节点入栈 while (head) { stack.push(head) head = head.next } // 获取头节点 let prev = head = stack.pop() || null // 弹栈组成反转后的链表 while (stack.length > 0) { const node = stack.pop() prev && (prev.next = node || null) prev = node || null } prev && (prev.next = null) return head }; -
反转操作其实就是把当前节点的 next 指向上一个节点,这样的话我们直接遍历一次就可以实现了
typescriptfunction reverseList(head: ListNode | null): ListNode | null { if (head === null || head.next === null) return head let prev: ListNode | null = null let cur: ListNode | null = head while (cur) { // 取得下一个节点并保存 const next = cur.next // 当前节点的 next 指向上一个节点 cur.next = prev // 移动上一节点指针到当前节点 prev = cur // 移动当前节点指针到下一个节点 cur = next } return prev } -
官方题解还提供了一种递归的解法,有点复杂这里我也讲一下吧。
我们假设链表一开始这样的
n(1)→n(2)→n(3)→n(4)→n(5)递归的本质就是递到最深层,再归回来处理
-
首先就是 递到最深层 ,当
head === null || head.next === null时,就到了递归的最里层,这时的head也就是n(5)就是反转后链表的head,我们通过newHead将它返回至最外层作为最终返回值。typescriptfunction reverseList(head: ListNode | null): ListNode | null { // 终止条件:空链表 或 遍历到最后一个节点n5 if (head === null || head.next === null) return head // 递:递归遍历下一个节点,直到找到n5(新头节点) const newHead = reverseList(head.next) // 返回n5作为反转后的head return newHead } -
然后我们就要在 归的过程 中进行反转操作:
最深层返回
n(5)后,回归到上一层,此时的head是n(4),我们需要把n(4)→n(5)变成n(5)→n(4)因为这里的
newHead一直都是n(5),我们只能通过head.next来实现反转。head.next.next = head,使n(5)→n(4)head.next = null, 把n(4)→n(5)的链接断开避免形成环形。然后到上一层
head变成n(3),把n(3)→n(4)转换成n(4)→n(3),以此类推就这样直到完成整个链表的反转。最终代码如下:
typescriptfunction reverseList(head: ListNode | null): ListNode | null { if (head === null || head.next === null) return head const newHead = reverseList(head.next) // 归:从n4开始,逐个反转节点指向 head.next.next = head; head.next = null; return newHead }
-
题目来源:力扣(LeetCode)