1. 奇偶链表问题解析
今天我们来聊聊链表操作中一个经典问题——奇偶链表重组。这个问题看似简单,但能很好地训练我们对链表指针操作的理解和把控能力。作为前端工程师,掌握这类基础算法问题对提升代码质量大有裨益。
问题描述很简单:给定一个单链表,要求将所有奇数位置的节点和偶数位置的节点分别分组,并保持它们原有的相对顺序,最后将偶数节点组接在奇数节点组后面。注意这里的"位置"指的是节点索引(从1开始计数),而不是节点值。
举个例子,对于链表 1->2->3->4->5:
- 奇数位置节点:1(位置1)、3(位置3)、5(位置5)
- 偶数位置节点:2(位置2)、4(位置4)
重组后应该得到 1->3->5->2->4
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解法思路与核心逻辑
2.1 基本解题思路
解决这个问题的关键在于如何高效地将原链表拆分为两个子链表,同时不占用额外空间。我的思路是:
- 维护两个指针:oddCurrent指向当前奇数节点,evenCurrent指向当前偶数节点
- 同时遍历原链表,将奇数节点链接到奇数链表,偶数节点链接到偶数链表
- 最后将偶数链表接在奇数链表末尾
这种方法的精妙之处在于它直接在原链表上进行操作,只需要几个指针变量,完全符合O(1)空间复杂度的要求。
2.2 边界情况处理
在实现时,有几个边界情况需要特别注意:
- 空链表:直接返回null
- 单节点链表:直接返回原链表
- 双节点链表:需要正确处理两个节点的连接关系
这些边界情况在代码中通过开头的条件判断来处理:
typescript复制if (head == null || head.next == null) return head
3. 代码实现详解
3.1 初始化阶段
typescript复制let oddCurrent = head // 奇数链表当前节点
let evenHead = head.next // 偶数链表头节点
let evenCurrent = head.next // 偶数链表当前节点
这里我们初始化三个关键指针:
- oddCurrent:始终指向奇数链表的最后一个节点
- evenHead:记录偶数链表的头节点(最后连接时需要)
- evenCurrent:始终指向偶数链表的最后一个节点
3.2 核心循环逻辑
typescript复制while (evenCurrent != null && evenCurrent.next != null) {
// 串联奇偶节点
oddCurrent.next = oddCurrent.next.next
evenCurrent.next = evenCurrent.next.next
// 移动奇偶节点指针
oddCurrent = oddCurrent.next
evenCurrent = evenCur
