当前位置: 首页 > news >正文

【C/C++】分隔链表 (leetcode T86)

核心考点预览:链表 (双指针)  技巧:虚拟头结点

题目描述:

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例 1:

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

示例 2:

输入:head = [2,1], x = 2
输出:[1,2]

提示:

  • 链表中节点的数目在范围 [0, 200] 内

  • -100 <= Node.val <= 100

  • -200 <= x <= 200

详细解答:

方法一:

// 定义链表节点结构
struct ListNode {
    int val; // 节点值
    struct ListNode *next; // 下一个节点指针
};

// 对链表进行分隔,使得所有小于x的节点在前,大于等于x的节点在后
struct ListNode* partition(struct ListNode* head, int x) {
    struct ListNode *p, *q, *res = (struct ListNode*)malloc(sizeof(struct ListNode));
    res->next = NULL; // 初始化头节点
    p = head; // p指针用于遍历原链表
    q = res; // q指针用于构建新链表,开始时指向虚拟头节点

    // 第一步:将所有小于x的节点放入新的链表
    while (p != NULL) {
        if (p->val < x) {
            struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
            temp->val = p->val; // 复制节点值
            temp->next = NULL;  // 设定新节点的next为NULL
            q->next = temp;     // 将新节点链接到当前链表
            q = temp;           // 更新q为新节点
        }
        p = p->next; // 移动到下一个节点
    }

    // 第二步:将所有大于等于x的节点放入新的链表
    p = head; // 重新指向原链表头
    while (p != NULL) {
        if (p->val >= x) {
            struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
            temp->val = p->val; // 复制节点值
            temp->next = NULL;  // 设定新节点的next为NULL
            q->next = temp;     // 将新节点链接到当前链表
            q = temp;           // 更新q为新节点
        }
        p = p->next; // 移动到下一个节点
    }

    // 返回分隔后的链表,跳过虚拟头节点
    return res->next;
}

题目解析

思路分析
  1. 两个链表:使用两个步骤,分别处理小于 x 和大于或等于 x 的节点,将它们合并在一个新链表中。
    • 第一步:遍历原链表,将所有小于 x 的节点复制到新链表中。
    • 第二步:重新遍历原链表,将所有大于或等于 x 的节点复制到新链表中。
  2. 注意:两个分区中的节点相对顺序保持不变。每次分配新节点时,我们保持链表顺序。
  3. 链表构建:需要两个指针 pq 来分别遍历原链表和构建新链表。
考点分析
  • 链表操作:链表的遍历、节点的插入,要求保留相对顺序。
  • 空间管理:每次插入一个新节点时,都需要使用 malloc 分配内存。
  • 时间复杂度:因为每次遍历整个链表,所以时间复杂度为 O(n),其中 n 是链表的长度。

这道题的难点在于如何分隔链表,并保证每个分区内的相对顺序不变。通过分两次遍历原链表并插入新的节点,可以有效地解决该问题。

易错点:

1.没有使用temp,导致原链表的顺序改变,在第二次遍历的时候走的都是第一轮改过的路径,即都走的是小于x的值

2.没有考虑下面这组测试用例:

head=[]  x=0;

如果没有在开始对res->next=NULL;的话,会导致最后返回的时候不知道res->next是什么

方法二:

// 定义链表节点结构
struct ListNode {
    int val; // 节点值
    struct ListNode *next; // 下一个节点指针
};

// 对链表进行分隔,使得所有小于x的节点在前,大于等于x的节点在后
struct ListNode* partition(struct ListNode* head, int x) {
    struct ListNode *cur, *p, *q, *res, *res1 = (struct ListNode*)malloc(sizeof(struct ListNode)), *res2 = (struct ListNode*)malloc(sizeof(struct ListNode));

    p = res1; // p指针用于构建小于x的链表
    q = res2; // q指针用于构建大于或等于x的链表
    cur = head; // cur指针用于遍历原链表

    // 遍历链表,将小于x的节点放入res1链表,大于等于x的节点放入res2链表
    while (cur != NULL) {
        if (cur->val < x) {
            p->next = cur; // 将cur节点加入res1链表
            p = p->next;   // 更新p为当前节点
        } else {
            q->next = cur; // 将cur节点加入res2链表
            q = q->next;   // 更新q为当前节点
        }
        cur = cur->next; // 移动到下一个节点
    }

    q->next = NULL; // 确保res2链表的尾部没有循环(结束)
    
    // 将res1链表和res2链表连接起来
    res = res1; // res指向小于x部分的虚拟头节点
    p->next = res2->next; // 将大于等于x的部分连接到小于x的部分后

    // 返回合并后的链表,从res->next开始
    return res->next;
}
易错点:

在最后添加 q->next=NULL; 以保证在主函数输出的时候能找到结尾

思路分析
  1. 虚拟头节点:通过 res1res2 虚拟头节点来分别存储小于 x 和大于等于 x 的节点。这样可以简化操作,避免在连接节点时处理特殊情况。
  2. 链表合并:遍历原链表,将小于 x 的节点放入 res1,大于等于 x 的节点放入 res2,最后将两个链表连接起来,保证了相对顺序不变。
  3. 连接步骤
    • 在遍历完链表后,pq 分别指向各自链表的尾部,将 res1res2 链表通过 p->nextq->next 连接起来。
    • 注意:q->next = NULL; 这一行代码用于确保 res2 链表最后的节点不再指向其他节点,避免形成环。

相关文章:

  • DeepSeek写俄罗斯方块手机小游戏
  • 图论 之 最小生成树
  • 深入解析Spring Cloud Config:构建高可用分布式配置中心
  • SpringBoot 新特性
  • C++ 设计模式-模板方法模式
  • 【ROS2】卡尔曼滤波学习:概念、数学推导和C++实现方法
  • 【Linux探索学习】第三十弹——线程互斥与同步(上):深入理解线程保证安全的机制
  • CPU、SOC、MPU、MCU--详细分析四者的区别
  • 【Springboot3】Springboot3 搭建RocketMQ 最简单案例
  • UE5 GamePlay 知识点
  • Powershell Install deepseek
  • 【JavaEE进阶】Spring MVC(4)-图书管理系统案例
  • Python 下载/安装
  • [免费]微信小程序智能商城系统(uniapp+Springboot后端+vue管理端)【论文+源码+SQL脚本】
  • 23.5.1 WebBrowser与网页交互
  • Python爬虫selenium验证-中文识别点选+图片验证码案例
  • Three.js 快速入门教程【六】相机控件 OrbitControls
  • MySql三大范式
  • 2025寒假周报4
  • Frp部署文档
  • 做冻品海鲜比较大的网站有哪些/it培训机构有哪些
  • 网站软件设计/seo知识培训
  • 专做特卖的网站/武汉百捷集团百度推广服务有限公司
  • 和平县做网站/浏览器打开网站
  • 企业网站做百度小程序/电商培训视频教程
  • 网站备案信息被注销/百度浏览器官网下载并安装