【算法】【链表】328.奇偶链表--通俗讲解

一、题目是啥?一句话说清

给定一个单链表,将所有奇数索引节点和偶数索引节点分别分组,保持原有顺序,然后将偶数索引节点组连接到奇数索引节点组之后。

示例:

  • 输入:1 → 2 → 3 → 4 → 5
  • 输出:1 → 3 → 5 → 2 → 4

二、解题核心

使用两个指针分别构建奇数链表和偶数链表,遍历原链表,将奇数节点连接在一起,偶数节点连接在一起,最后将偶数链表头连接到奇数链表尾。

这就像把队伍分成男女两组,然后让男组在前,女组在后,但每组内部保持原来的顺序。

三、关键在哪里?(3个核心点)

想理解并解决这道题,必须抓住以下三个关键点:

1. 分离奇偶节点

  • 是什么:使用两个指针odd和even,odd指向奇数节点,even指向偶数节点。
  • 为什么重要:这样我们可以同时遍历和构建两个链表,而不需要额外空间。

2. 维护两个链表的头部

  • 是什么:保存偶数链表的头节点evenHead,因为最后需要将偶数链表连接到奇数链表之后。
  • 为什么重要:如果不保存evenHead,我们将丢失偶数链表的起点,无法连接。

3. 指针移动和连接

  • 是什么:在遍历过程中,将odd的next指向odd的下一个奇数节点(即odd->next->next),同样对even做类似操作。
  • 为什么重要:这确保了奇数节点和偶数节点分别被正确连接,形成两个独立的链表。

四、看图理解流程(通俗理解版本)

假设链表为:1 → 2 → 3 → 4 → 5

  1. 初始化

    • odd指向头节点1(奇数索引)
    • even指向头节点的下一个节点2(偶数索引)
    • 保存evenHead = 2(偶数链表的头)
  2. 第一轮处理

    • 将odd的next指向odd->next->next(即1指向3):1 → 3
    • 将even的next指向even->next->next(即2指向4):2 → 4
    • 移动odd到odd->next(即3)
    • 移动even到even->next(即4)
  3. 第二轮处理

    • odd的next指向odd->next->next(即3指向5):1 → 3 → 5
    • even的next指向even->next->next(即4指向null):2 → 4 → null
    • 移动odd到5
    • 移动even到null
  4. 连接链表

    • 此时奇数链表:1 → 3 → 5
    • 偶数链表:2 → 4
    • 将odd的next指向evenHead:5指向2,形成1 → 3 → 5 → 2 → 4

五、C++ 代码实现(附详细注释)

cpp 复制代码
#include <iostream>
using namespace std;

// 链表节点定义
struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};

class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) {
            return head; // 空链表或只有一个节点,直接返回
        }
        
        ListNode* odd = head; // 奇数指针,指向头节点
        ListNode* even = head->next; // 偶数指针,指向第二个节点
        ListNode* evenHead = even; // 保存偶数链表的头节点
        
        // 遍历链表,直到even或even->next为空
        while (even != nullptr && even->next != nullptr) {
            // 将odd的next指向下一个奇数节点
            odd->next = odd->next->next;
            // 将even的next指向下一个偶数节点
            even->next = even->next->next;
            // 移动odd和even指针
            odd = odd->next;
            even = even->next;
        }
        
        // 将偶数链表连接到奇数链表之后
        odd->next = evenHead;
        
        return head;
    }
};

// 辅助函数:打印链表
void printList(ListNode* head) {
    while (head != nullptr) {
        cout << head->val << " ";
        head = head->next;
    }
    cout << endl;
}

// 测试代码
int main() {
    // 创建示例链表:1->2->3->4->5
    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(4);
    head->next->next->next->next = new ListNode(5);
    
    Solution solution;
    ListNode* result = solution.oddEvenList(head);
    
    printList(result); // 输出:1 3 5 2 4
    
    // 释放内存(简单示例)
    while (result != nullptr) {
        ListNode* temp = result;
        result = result->next;
        delete temp;
    }
    
    return 0;
}

六、时间空间复杂度

  • 时间复杂度:O(n),其中n是链表长度。我们只遍历了一次链表。
  • 空间复杂度:O(1),只使用了几个指针,没有使用额外空间。

七、注意事项

  • 边界条件:处理空链表或只有一个节点的情况,直接返回头节点。
  • 循环条件:循环继续的条件是even不为空且even->next不为空,因为even指针每次移动两步,需要确保even->next存在。
  • 指针移动:在更新odd和even的next指针后,需要移动odd和even指针到下一个位置。
  • 连接链表:最后一定要将奇数链表的尾部指向偶数链表的头部,否则会丢失偶数部分。

算法通俗讲解推荐阅读
【算法--链表】83.删除排序链表中的重复元素--通俗讲解
【算法--链表】删除排序链表中的重复元素 II--通俗讲解
【算法--链表】86.分割链表--通俗讲解
【算法】92.翻转链表Ⅱ--通俗讲解
【算法--链表】109.有序链表转换二叉搜索树--通俗讲解
【算法--链表】114.二叉树展开为链表--通俗讲解
【算法--链表】116.填充每个节点的下一个右侧节点指针--通俗讲解
【算法--链表】117.填充每个节点的下一个右侧节点指针Ⅱ--通俗讲解
【算法--链表】138.随机链表的复制--通俗讲解
【算法】143.重排链表--通俗讲解
【算法--链表】146.LRU缓存--通俗讲解
【算法--链表】147.对链表进行插入排序--通俗讲解
【算法】【链表】148.排序链表--通俗讲解
【算法】【链表】160.相交链表--通俗讲解
【算法】【链表】203.移除链表元素--通俗讲解
【算法】【链表】206.反转链表--通俗讲解
【算法】234.回文链表--通俗讲解
【算法】【链表】237.删除链表中的节点--通俗讲解


关注公众号,获取更多底层机制/ 算法通俗讲解干货!

相关推荐
Coovally AI模型快速验证15 分钟前
当视觉语言模型接收到相互矛盾的信息时,它会相信哪个信号?
人工智能·深度学习·算法·机器学习·目标跟踪·语言模型
电院工程师1 小时前
SIMON64/128算法Verilog流水线实现(附Python实现)
python·嵌入式硬件·算法·密码学
轮到我狗叫了1 小时前
力扣.84柱状图中最大矩形 力扣.134加油站牛客.abb(hard 动态规划+哈希表)牛客.哈夫曼编码
算法·leetcode·职场和发展
丛雨要玩游戏1 小时前
字符函数和字符串函数
c语言·开发语言·算法
八个程序员1 小时前
自定义函数(C++)
开发语言·c++·算法
ad钙奶长高高1 小时前
【C语言】初始C语言
c语言·开发语言·算法
罗西的思考1 小时前
【Agent】 ACE(Agentic Context Engineering)源码阅读笔记---(3)关键创新
人工智能·算法
XiaoYu20022 小时前
第1章 核心竞争力和职业规划
前端·面试·程序员
报错小能手3 小时前
C++笔记(面向对象)静态联编和动态联编
开发语言·c++·算法
WBluuue3 小时前
AtCoder Beginner Contest 430(ABCDEF)
c++·算法