单链表反转:从基础到进阶的完整指南

单链表反转是数据结构与算法中的经典问题,它不仅考察对链表结构的理解,也考验编程思维和技巧。本文将带你从基础实现到高级应用,全面掌握单链表反转。

1. 理解单链表

在深入反转算法之前,我们先回顾单链表的基本结构:

python 复制代码
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

单链表的特点是每个节点包含数据和指向下一个节点的指针,只能单向遍历。

2. 基础反转方法

2.1 迭代法(最常用)

核心思想:逐个改变节点指向,从前往后反转。

python 复制代码
def reverse_list_iterative(head):
    prev = None
    current = head
    
    while current:
        # 保存下一个节点
        next_temp = current.next
        # 反转指针
        current.next = prev
        # 移动指针
        prev = current
        current = next_temp
    
    return prev  # 新的头节点

执行过程可视化

python 复制代码
原链表: 1 → 2 → 3 → 4 → 5 → None

步骤1: None ← 1  2 → 3 → 4 → 5 → None
步骤2: None ← 1 ← 2  3 → 4 → 5 → None
步骤3: None ← 1 ← 2 ← 3  4 → 5 → None
...
结果: None ← 1 ← 2 ← 3 ← 4 ← 5

2.2 递归法

核心思想:通过递归到达链表末端,然后从后往前反转。

python 复制代码
def reverse_list_recursive(head):
    # 递归终止条件
    if not head or not head.next:
        return head
    
    # 递归到最后一个节点
    new_head = reverse_list_recursive(head.next)
    
    # 反转指针
    head.next.next = head
    head.next = None
    
    return new_head

递归过程分析

scss 复制代码
reverse(1)
  reverse(2)
    reverse(3)
      reverse(4)
        reverse(5) → 返回5
      5.next = 4, 4.next = None
    5.next = 3, 3.next = None
  5.next = 2, 2.next = None
5.next = 1, 1.next = None

3. 进阶反转技巧

3.1 反转部分链表

反转链表中从位置 m 到 n 的部分:

python 复制代码
def reverse_between(head, m, n):
    if not head or m == n:
        return head
    
    dummy = ListNode(0)
    dummy.next = head
    prev = dummy
    
    # 移动到第m-1个节点
    for _ in range(m - 1):
        prev = prev.next
    
    # 开始反转
    current = prev.next
    for _ in range(n - m):
        temp = current.next
        current.next = temp.next
        temp.next = prev.next
        prev.next = temp
    
    return dummy.next

3.2 K个一组反转链表

每 k 个节点一组进行反转,不足 k 的保持原样:

python 复制代码
def reverse_k_group(head, k):
    def reverse_sublist(start, end):
        prev, curr = None, start
        while curr != end:
            next_temp = curr.next
            curr.next = prev
            prev = curr
            curr = next_temp
        return prev
    
    # 检查是否有k个节点
    node = head
    for _ in range(k):
        if not node:
            return head
        node = node.next
    
    # 反转前k个节点
    new_head = reverse_sublist(head, node)
    # 递归处理剩余部分
    head.next = reverse_k_group(node, k)
    
    return new_head

3.3 交替反转

第一个k个节点反转,下一个k个节点保持,如此交替:

python 复制代码
def reverse_alternate_k_nodes(head, k):
    if not head or k <= 1:
        return head
    
    current = head
    prev = None
    reverse = True
    
    while current:
        if reverse:
            # 反转k个节点
            section_start = current
            section_prev = None
            count = 0
            
            # 检查是否有足够的节点
            temp = current
            for _ in range(k):
                if not temp:
                    break
                temp = temp.next
            
            # 反转当前段
            while current and count < k:
                next_temp = current.next
                current.next = section_prev
                section_prev = current
                current = next_temp
                count += 1
            
            # 连接已反转部分
            if prev:
                prev.next = section_prev
            else:
                head = section_prev
            
            section_start.next = current
            prev = section_start
            reverse = False
        else:
            # 跳过k个节点
            count = 0
            while current and count < k:
                prev = current
                current = current.next
                count += 1
            reverse = True
    
    return head

4. 特殊场景反转

4.1 反转链表的前N个节点

python 复制代码
def reverse_first_n(head, n):
    successor = None
    
    def reverse_n(node, count):
        nonlocal successor
        if count == 1:
            successor = node.next
            return node
        
        last = reverse_n(node.next, count - 1)
        node.next.next = node
        node.next = successor
        return last
    
    return reverse_n(head, n)

4.2 从末尾开始反转

python 复制代码
def reverse_from_end(head, k):
    # 先找到总长度
    length = 0
    current = head
    while current:
        length += 1
        current = current.next
    
    # 转换为从头开始的位置
    m = length - k + 1
    return reverse_between(head, m, length)

5. 性能分析与比较

方法 时间复杂度 空间复杂度 适用场景
迭代法 O(n) O(1) 通用,最常用
递归法 O(n) O(n) 代码简洁,栈深度受限
部分反转 O(n) O(1) 局部操作
K组反转 O(n) O(n/k) 批量处理

6. 实战技巧与注意事项

6.1 边界情况处理

  • 空链表
  • 单节点链表
  • 反转位置超出范围
  • k值大于链表长度

6.2 调试技巧

python 复制代码
def print_list(head):
    """打印链表用于调试"""
    result = []
    current = head
    while current:
        result.append(str(current.val))
        current = current.next
    print(" → ".join(result) + " → None")

6.3 常见错误

  1. 忘记处理头节点的更新
  2. 指针丢失(在改变next前未保存)
  3. 循环链表的形成
  4. 边界条件处理不完整

7. 综合练习

题目:给定链表 1→2→3→4→5→6→7,要求实现:

  1. 完全反转
  2. 反转2-5位置
  3. 每3个一组反转
  4. 交替每2个节点反转
python 复制代码
# 测试用例
def create_sample_list():
    nodes = [ListNode(i) for i in range(1, 8)]
    for i in range(len(nodes)-1):
        nodes[i].next = nodes[i+1]
    return nodes[0]

# 测试各种反转方法
head = create_sample_list()
print("原链表:")
print_list(head)

print("\n完全反转:")
print_list(reverse_list_iterative(create_sample_list()))

print("\n反转位置2-5:")
print_list(reverse_between(create_sample_list(), 2, 5))

print("\n每3个一组反转:")
print_list(reverse_k_group(create_sample_list(), 3))

总结

单链表反转是算法学习中的重要里程碑。掌握从基础到进阶的各种反转技巧,不仅能够解决链表相关问题,更能培养严谨的编程思维和指针操作能力。建议通过大量练习来熟练掌握这些技巧,并理解每种方法适用的场景。

记住:多画图理解指针变化,多写代码加深印象,这是掌握链表问题的关键!

相关推荐
Chenyiax9 小时前
从 Chat 到 Responses:OpenAI API 抽象为什么变了?
后端
MariaH9 小时前
Koa和Express的区别
后端
MariaH9 小时前
Koa框架的使用
后端
luckdewei10 小时前
那个用 passlib 做认证的新同事,上线第一天就把用户密码写进了日志
后端
ping某11 小时前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
JustHappy11 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom11 小时前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github
用户14748530797416 小时前
CodeX使用Skill生成游戏美术和音乐资源,一分钟入门
后端
Melody12316 小时前
用 abort 中断 AI 流式请求,我之前做错了
后端
onething36516 小时前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 5 —— SSE 流式输出 + 打字机效果
人工智能·后端·全栈