三种方法解——力扣206.反转链表
力扣206.反转链表
【三种方式彻底吃透】LeetCode 206. 反转链表:迭代、递归与栈的全思路解析
题目描述
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
提示:
- 链表中节点的数目范围为
[0, 5000]
-5000 <= Node.val <= 5000
思路总览
反转链表的本质是——把每个节点的指针方向反过来。
原链表:
1 → 2 → 3 → 4 → 5 → null
反转后:
null ← 1 ← 2 ← 3 ← 4 ← 5
解法一:迭代法(双指针 · 最常用)
思路解析
使用三个指针:
prev
:当前节点的前一个节点;curr
:当前节点;next
:暂存下一个节点,防止断链。
不断执行以下步骤:
- 暂存
next = curr.next
- 反转指针
curr.next = prev
- 前移指针:
prev = curr
,curr = next
- 当
curr == null
时,prev
就是新的头节点
代码实现
class Solution {public ListNode reverseList(ListNode head) {ListNode prev = null;ListNode curr = head;while (curr != null) {ListNode next = curr.next; // 暂存下一个节点curr.next = prev; // 反转指针prev = curr; // 前移 prevcurr = next; // 前移 curr}return prev; // prev 为反转后的新头节点}
}
解法二:递归法(结构优雅 · 思维跳跃)
思路解析
递归地反转剩余的子链表,然后让下一个节点指向自己:
-
递归出口:
head == null
或head.next == null
,直接返回head
-
递归调用:
ListNode newHead = reverseList(head.next)
-
反转当前指向:
head.next.next = head
head.next = null
-
返回
newHead
(新头节点)
代码实现
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;}
}
解法三:栈法(逻辑直观 · 空间换时间)
思路解析
利用 栈 的 “后进先出” 特性反转链表:
- 遍历链表,将所有节点压入栈;
- 依次弹出节点,重新连接;
- 注意:弹出最后一个节点后,要将其
next
设为null
。
这种方法结构直观,适合初学者理解指针反转的原理。
代码实现
class Solution {public ListNode reverseList(ListNode head) {if (head == null) return null;Stack<ListNode> stack = new Stack<>();ListNode curr = head;while (curr != null) {stack.push(curr);curr = curr.next;}// 弹出第一个节点作为新头ListNode newHead = stack.pop();ListNode node = newHead;while (!stack.isEmpty()) {node.next = stack.pop();node = node.next;}node.next = null; // 最后一个节点指向 nullreturn newHead;}
}
复杂度分析
方法 | 时间复杂度 | 空间复杂度 | 特点 |
---|---|---|---|
迭代法 | O(n) | O(1) | 实用最高效 |
递归法 | O(n) | O(n)(递归栈) | 简洁优雅 |
栈法 | O(n) | O(n)(显式栈) | 思路直观 |
反转链表,就是让每个节点的
next
指向它的前一个节点——
无论是指针、递归还是栈,思路的核心都在“反转方向”。