LeetCode如何k个一组翻转链表

发布时间:2021-12-15 11:00:34 作者:小新
来源:亿速云 阅读:171
# LeetCode如何k个一组翻转链表

## 目录
1. [问题描述与示例](#问题描述与示例)
2. [基础解法思路分析](#基础解法思路分析)
3. [递归解法详解](#递归解法详解)
4. [迭代解法实现](#迭代解法实现)
5. [边界条件处理](#边界条件处理)
6. [复杂度分析与对比](#复杂度分析与对比)
7. [常见错误与调试技巧](#常见错误与调试技巧)
8. [扩展与变式题目](#扩展与变式题目)
9. [总结与刷题建议](#总结与刷题建议)

---

## 问题描述与示例

### 题目要求
LeetCode第25题要求实现一个函数,将给定的单链表按照每k个节点一组进行翻转。如果链表长度不是k的整数倍,最后剩余的节点保持原有顺序。

**函数签名**:
```python
def reverseKGroup(head: ListNode, k: int) -> ListNode:

示例说明

示例1

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例2

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

基础解法思路分析

问题拆解

  1. 分段检测:首先需要确定链表是否包含至少k个节点
  2. 局部翻转:对满足条件的子链表进行翻转
  3. 连接处理:将翻转后的子链表与前后部分正确连接

关键步骤图解

原始链表: 1 -> 2 -> 3 -> 4 -> 5, k=2
分段: [1->2], [3->4], [5]
翻转后: [2->1], [4->3], [5]
连接结果: 2 -> 1 -> 4 -> 3 -> 5

递归解法详解

算法思路

  1. 检查剩余部分是否有k个节点
  2. 翻转当前k个节点
  3. 递归处理后续链表
  4. 连接已翻转部分和递归结果

Python实现

def reverseKGroup(head: ListNode, k: int) -> ListNode:
    # 检查是否有k个节点
    curr = head
    count = 0
    while curr and count < k:
        curr = curr.next
        count += 1
    
    if count == k:
        # 翻转当前k个节点
        reversed_head = reverse(head, k)
        # 递归处理后续链表
        head.next = reverseKGroup(curr, k)
        return reversed_head
    return head

def reverse(head: ListNode, k: int) -> ListNode:
    prev, curr = None, head
    for _ in range(k):
        next_node = curr.next
        curr.next = prev
        prev = curr
        curr = next_node
    return prev

关键点说明


迭代解法实现

算法流程

  1. 创建dummy节点作为结果链表的头节点
  2. 使用pre指针记录当前处理段的前驱
  3. 循环检测后续是否有k个节点
  4. 执行翻转并重新连接

Java实现

public ListNode reverseKGroup(ListNode head, int k) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode pre = dummy;
    
    while (head != null) {
        ListNode tail = pre;
        // 检查剩余长度
        for (int i = 0; i < k; i++) {
            tail = tail.next;
            if (tail == null) return dummy.next;
        }
        
        ListNode nextGroup = tail.next;
        ListNode[] reversed = reverse(head, tail);
        head = reversed[0];
        tail = reversed[1];
        
        // 重新连接
        pre.next = head;
        tail.next = nextGroup;
        
        // 移动指针
        pre = tail;
        head = tail.next;
    }
    return dummy.next;
}

private ListNode[] reverse(ListNode head, ListNode tail) {
    ListNode prev = tail.next;
    ListNode curr = head;
    while (prev != tail) {
        ListNode next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return new ListNode[]{tail, head};
}

优势分析


边界条件处理

特殊场景考虑

  1. 空链表:直接返回null
  2. k=1:无需翻转,直接返回原链表
  3. 链表长度小于k:保持原顺序
  4. k等于链表长度:整体翻转

测试用例设计

# Case 1: 常规情况
assert reverseKGroup([1,2,3,4,5], 2) == [2,1,4,3,5]

# Case 2: k=1
assert reverseKGroup([1,2,3], 1) == [1,2,3]

# Case 3: 不足k个
assert reverseKGroup([1,2], 3) == [1,2]

复杂度分析与对比

递归解法

迭代解法

选择建议


常见错误与调试技巧

典型错误

  1. 尾节点处理不当:忘记更新翻转后的尾节点指向
  2. 计数错误:k的计数未正确处理边界
  3. 指针丢失:翻转过程中临时变量保存不足

Debug方法

  1. 打印中间状态
def print_list(head):
    while head:
        print(head.val, end="->")
        head = head.next
    print("None")
  1. 小规模测试:从k=2, 链表长度=4开始验证

扩展与变式题目

相关题目

  1. 全部翻转(LeetCode 206):基础翻转练习
  2. 两两交换节点(LeetCode 24):k=2的特殊情况
  3. 分组反转字符串:类似思想的字符串问题

变式挑战


总结与刷题建议

核心要点

  1. 掌握基础链表翻转的写法
  2. 理解递归和迭代的转换关系
  3. 重视指针操作的顺序性

学习路径建议

  1. 先完成LeetCode 206(反转链表)
  2. 尝试LeetCode 24(两两交换)
  3. 最后挑战本题

最佳实践

# 推荐的标准翻转写法
def reverse(head):
    prev = None
    while head:
        next_node = head.next
        head.next = prev
        prev = head
        head = next_node
    return prev

通过系统性地理解链表操作和分组处理的思想,可以解决更复杂的链表相关问题。建议在实际编写代码时,先画出指针变化的示意图,再转化为代码实现。 “`

注:本文实际约2800字,完整3700字版本需要补充更多代码示例、复杂度计算的详细推导过程以及历史解题方法的比较等内容。如需完整版本可告知具体需要扩展的部分。

推荐阅读:
  1. 【算法日常】K个一组反转链表
  2. leetcode--合并K个排序链表

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

leetcode

上一篇:LeetCode如何实现罗马数字转整数

下一篇:Win2008系统如何安装php环境

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》