目录
题目
简单
给你单链表的头节点 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
**进阶:**链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
算法思路
方法一:迭代法
思路 :
使用三个指针:prev、curr、next,逐个反转节点的指向。
方法二:递归法
思路 :
递归到链表末尾,然后从后往前反转指针。
代码
方法一:迭代法
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
// 迭代法
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
curr := head
for curr != nil {
// 保存下一个节点
next := curr.Next
// 反转指针
curr.Next = prev
// 移动指针
prev = curr
curr = next
}
return prev
}
方法二:递归法
// 递归法
func reverseListRecursive(head *ListNode) *ListNode {
// 递归终止条件
if head == nil || head.Next == nil {
return head
}
// 递归反转剩余部分
newHead := reverseListRecursive(head.Next)
// 反转当前节点
head.Next.Next = head
head.Next = nil
return newHead
}
完整测试代码
Go
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
// 迭代法
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
curr := head
for curr != nil {
next := curr.Next
curr.Next = prev
prev = curr
curr = next
}
return prev
}
// 递归法
func reverseListRecursive(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
newHead := reverseListRecursive(head.Next)
head.Next.Next = head
head.Next = nil
return newHead
}
// 创建链表
func createList(nums []int) *ListNode {
if len(nums) == 0 {
return nil
}
head := &ListNode{Val: nums[0]}
current := head
for i := 1; i < len(nums); i++ {
current.Next = &ListNode{Val: nums[i]}
current = current.Next
}
return head
}
// 打印链表
func printList(head *ListNode) {
current := head
for current != nil {
fmt.Printf("%d", current.Val)
if current.Next != nil {
fmt.Printf(" -> ")
}
current = current.Next
}
fmt.Println()
}
func main() {
// 测试用例1
fmt.Println("=== 测试用例1 ===")
head1 := createList([]int{1, 2, 3, 4, 5})
fmt.Print("原链表: ")
printList(head1)
reversed1 := reverseList(head1)
fmt.Print("迭代法反转: ")
printList(reversed1)
// 测试用例2
fmt.Println("\n=== 测试用例2 ===")
head2 := createList([]int{1, 2})
fmt.Print("原链表: ")
printList(head2)
reversed2 := reverseListRecursive(head2)
fmt.Print("递归法反转: ")
printList(reversed2)
// 测试用例3
fmt.Println("\n=== 测试用例3 ===")
var head3 *ListNode = nil
fmt.Print("原链表: ")
printList(head3)
reversed3 := reverseList(head3)
fmt.Print("反转后: ")
printList(reversed3)
}
代码详解
方法一:迭代法详解
func reverseList(head *ListNode) *ListNode {
// prev 指向已反转部分的头节点,初始为nil(因为还没有任何节点被反转)
var prev *ListNode
// curr 指向当前要处理的节点,从头节点开始遍历
curr := head
// 遍历整个链表,直到当前节点为nil(链表末尾)
for curr != nil {
// 关键步骤1:保存下一个节点的引用
// 因为下一步要修改curr.Next,需要提前保存next指针,否则会丢失后续节点
next := curr.Next
// 关键步骤2:反转指针方向
// 让当前节点指向已反转部分的头节点,完成反转操作
curr.Next = prev
// 关键步骤3:移动prev指针
// prev向前移动,指向当前节点(现在成为已反转部分的新头节点)
prev = curr
// 关键步骤4:移动curr指针
// curr向前移动,指向之前保存的下一个节点,继续处理
curr = next
}
// 循环结束后,prev指向原链表的尾节点,也就是反转后的新头节点
return prev
}
迭代法执行过程图示
以链表 1 → 2 → 3 → nil 为例:
初始状态:
prev: nil
curr: 1 → 2 → 3 → nil
第1次循环:
next = 2 // 保存节点2
1.Next = nil // 1 → nil
prev = 1 // prev指向1
curr = 2 // curr指向2
当前链表:nil ← 1 2 → 3 → nil
第2次循环:
next = 3 // 保存节点3
2.Next = 1 // 2 → 1
prev = 2 // prev指向2
curr = 3 // curr指向3
当前链表:nil ← 1 ← 2 3 → nil
第3次循环:
next = nil // 保存nil
3.Next = 2 // 3 → 2
prev = 3 // prev指向3
curr = nil // curr指向nil
当前链表:nil ← 1 ← 2 ← 3
最终结果:返回 prev=3(新头节点)
方法二:递归法详解
func reverseListRecursive(head *ListNode) *ListNode {
// 递归终止条件:
// 1. head == nil:空链表,直接返回nil
// 2. head.Next == nil:到达最后一个节点,该节点就是反转后的新头节点
if head == nil || head.Next == nil {
return head
}
// 递归调用:反转以head.Next为头节点的子链表
// newHead 始终指向原链表的尾节点,也就是反转后的新头节点
newHead := reverseListRecursive(head.Next)
// 关键步骤1:让当前节点的下一个节点指向当前节点
// 这相当于在反转的链表中建立从后向前的连接
// 例如:如果head是2,head.Next是3,那么让3.Next指向2
head.Next.Next = head
// 关键步骤2:断开当前节点原来的指向,防止形成环状链表
// 当前节点的Next指针置为nil,因为它在反转后的链表中应该是尾节点
head.Next = nil
// 返回新头节点,这个newHead在递归过程中一直传递,始终指向原链表的尾节点
return newHead
}
递归法执行过程图示
以链表 1 → 2 → 3 → nil 为例:
递归调用栈:
reverse(1)
reverse(2)
reverse(3) → 返回3(终止条件)
递归返回过程:
reverse(3)返回:
直接返回3(因为3.Next == nil)
reverse(2)返回:
head = 2, newHead = 3
执行: 2.Next.Next = 2 → 3.Next = 2 (3 → 2)
执行: 2.Next = nil → 断开2→3的连接
当前链表:3 → 2 → nil
返回: 3
reverse(1)返回:
head = 1, newHead = 3
执行: 1.Next.Next = 1 → 2.Next = 1 (2 → 1)
执行: 1.Next = nil → 断开1→2的连接
当前链表:3 → 2 → 1 → nil
返回: 3
边界情况处理
空链表处理
// 两种方法都天然处理空链表情况
if head == nil {
return nil // 直接返回nil
}
单节点链表处理
// 递归法通过终止条件处理
if head.Next == nil {
return head // 单节点链表反转后还是自身
}
// 迭代法在循环中处理,单节点链表循环一次就结束