2074. 反转偶数长度组的节点

反转偶数长度组的链表 —— 分组 + 链表反转技巧实战

链表是常见的数据结构,在算法面试中出现频率极高。本文将讲解一道稍有难度的链表题目,涉及分组、子链表反转等技巧,适合进阶刷题者深入理解链表操作。


🧩 题目描述

给定一个单链表的头节点 head,请你将链表按照如下规律分组:

  • 第1组长度为1(即第一个节点)
  • 第2组长度为2(即接下来的两个节点)
  • 第3组长度为3,以此类推……

注意:

  • 最后一组的实际长度可以小于预期(例如只剩2个节点分不到长度为4的一组)。
  • 对于每个偶数长度的组,需要将该组的节点反转

示例 1

输入:head = [5,2,6,3,9,1,7,3,8,4]
输出:[5,6,2,3,9,1,4,8,3,7]

解释:
- 第一组 [5] 长度为1,不反转。
- 第二组 [2,6] 长度为2,反转为 [6,2]
- 第三组 [3,9,1] 长度为3,不反转。
- 第四组 [7,3,8,4] 长度为4,反转为 [4,8,3,7]

示例 2

输入:head = [1,1,0,6]
输出:[1,0,1,6]

🔍 解题分析

🧠 核心思路

  1. 分组遍历链表: 每一轮从当前节点开始,尝试收集 group_size 个节点为一组。
  2. 判断组长度是否为偶数: 如果是,则反转该组;否则跳过。
  3. 反转子链表: 用常规链表反转方法,对某一段长度为 k 的子链表进行原地反转。
  4. 维护前后连接关系: 反转完后,将前一段尾部和下一段首部连接好。

🔧 解题方法:Python 实现

我们将该思路转化为 Python 代码,并对关键细节注释说明:

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def reverseEvenLengthGroups(self, head: Optional[ListNode]) -> Optional[ListNode]:
        group_size = 1
        prev = None
        curr = head

        while curr:
            count = 0
            temp = curr

            # 统计实际组长度(可能不足 group_size)
            while count < group_size and temp:
                temp = temp.next
                count += 1

            # 当前组的开头和结尾
            group_head = curr
            group_tail = curr
            for _ in range(count - 1):
                group_tail = group_tail.next

            next_group = group_tail.next if group_tail else None

            # 如果为偶数长度,反转该组
            if count % 2 == 0:
                prev_node = next_group
                node = group_head
                for _ in range(count):
                    nxt = node.next
                    node.next = prev_node
                    prev_node = node
                    node = nxt

                if prev:
                    prev.next = group_tail
                else:
                    head = group_tail

                prev = group_head
                curr = next_group
            else:
                prev = group_tail
                curr = next_group

            group_size += 1

        return head

🧪 示例说明与测试

我们使用辅助函数构建链表并打印结果,验证效果。

def build_list(arr):
    dummy = ListNode(0)
    curr = dummy
    for val in arr:
        curr.next = ListNode(val)
        curr = curr.next
    return dummy.next

def print_list(head):
    res = []
    while head:
        res.append(head.val)
        head = head.next
    print(res)

# 测试用例
head = build_list([5,2,6,3,9,1,7,3,8,4])
sol = Solution()
res = sol.reverseEvenLengthGroups(head)
print_list(res)  # 输出应为 [5,6,2,3,9,1,4,8,3,7]

⚖️ 方法分析与比较

方面本题解法分析
时间复杂度O(n),每个节点访问一次,反转操作为 O(k),总体仍为线性
空间复杂度O(1),仅使用常数额外空间进行原地操作
可读性高,分组、反转逻辑独立清晰
鲁棒性良好,考虑了链表结尾不足一组长度的边界情况

🏁 总结

这道题考察了:

  • 链表遍历技巧
  • 分组逻辑与长度计算
  • 子链表的原地反转
  • 链表指针连接的精确控制

如果你对链表不够熟练,这道题可能一开始有些复杂,但一旦掌握了 “遍历+分组+条件反转+拼接” 这个套路,许多链表题目也就迎刃而解了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值