算法题题解:分隔链表

news/2024/9/30 0:13:18 标签: 算法, 链表, 数据结构

Problem: 86. 分隔链表

题目描述:

给定一个链表和一个值 x,要求将链表重新排列,所有小于 x 的节点放在前面,所有大于或等于 x 的节点放在后面。要求保留节点的相对顺序。


解题思路:

因为是链表而不是数组,构建子链不增加空间复杂度。勇敢地构造子链即可,无需考虑节点交换。

我们可以通过创建两个链表来分别存储小于 x 和大于等于 x 的节点,并最终将这两个链表连接起来。这种方法可以保证在一次遍历链表的过程中完成分割操作。

具体步骤如下:

  1. 虚拟头节点:使用两个虚拟头节点,一个用于保存小于 x 的节点链表,另一个用于保存大于等于 x 的节点链表。虚拟头节点可以简化链表操作,避免处理头节点的特殊情况。

  2. 遍历链表:通过遍历原始链表,遇到小于 x 的节点,放入小于 x链表;遇到大于或等于 x 的节点,放入大于等于 x链表

  3. 连接链表:遍历完成后,将两个链表连接起来,并确保大于等于 x链表末尾指向 NULL,防止形成环。

  4. 返回新链表:最后返回重新排列后的链表头部。


解题过程:

  1. 定义虚拟头节点:使用 lowDummyhighDummy 作为小于 x 和大于等于 x链表的虚拟头节点。

  2. 遍历链表:我们通过遍历原始链表,将每个节点根据其值加入对应的链表lowhigh)。

  3. 处理边界情况:遍历结束后,确保大于等于 x链表NULL 结尾。

  4. 连接两个链表:将小于 x链表的末尾与大于等于 x链表的头部连接起来。


代码实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* partition(struct ListNode* head, int x) {
    // 定义两个虚拟头节点,分别用于存放小于x的和大于等于x的节点
    struct ListNode lowDummy, highDummy;
    
    // 初始化两个指针用于遍历链表并构建两个链表
    struct ListNode *low = &lowDummy, *high = &highDummy;
    struct ListNode *p = head;
    
    // 初始化虚拟头节点的next指针为空,防止产生垃圾数据
    lowDummy.next = NULL;
    highDummy.next = NULL;
    
    // 遍历原链表并进行分割
    while (p) {
        if (p->val < x) {
            low->next = p;  // 将当前节点加入到小于x的链表
            low = low->next;
        } else {
            high->next = p;  // 将当前节点加入到大于等于x的链表
            high = high->next;
        }
        p = p->next;  // 移动到下一个节点
    }

    // 终止大于等于x的链表,防止形成环
    high->next = NULL;
    
    // 将小于x的链表与大于等于x的链表连接起来
    low->next = highDummy.next;

    // 返回小于x的链表头部
    return lowDummy.next;
}

复杂度分析:

  1. 时间复杂度:O(n)

    • 我们只遍历一次链表,进行一次分割和连接操作,因此时间复杂度为 O(n),其中 n链表中的节点个数。
  2. 空间复杂度:O(1)

    • 只用了几个指针来保存链表的分割和连接状态,并没有使用额外的空间来存储数据,因此空间复杂度为 O(1)。

总结:

通过使用两个虚拟头节点,我们可以很方便地将链表中的节点分割成两部分(小于 x 和大于等于 x),并在最后将它们连接起来。这样不仅简化了代码结构,而且避免了复杂的头节点处理,使得代码更为简洁明了。

这种方法在时间和空间上都具有较好的性能,适合处理大规模链表的分隔问题。


这篇文章详细描述了解题思路、代码实现和复杂度分析,供大家参考学习。
谢谢观看!


http://www.niftyadmin.cn/n/5683947.html

相关文章

企业级移动应用管理平台哪个好?

在当今数字化转型的浪潮中&#xff0c;企业级移动应用管理平台&#xff08;Enterprise Mobile Application Management, EMAM&#xff09;已成为许多企业提升运营效率、加强团队协作与提高工作灵活性的关键工具。这类平台帮助企业安全、有效地管理和部署移动应用程序&#xff0…

C#基于SkiaSharp实现印章管理(10)

向PDF文件插入印章图片比之前实现的向图片文件插入印章麻烦得多。   最初的想法是使用PDF浏览控件在线打开PDF文件&#xff0c;然后在控件中实现鼠标移动时动态显示印章&#xff0c;点击鼠标时向当前PDF页面的鼠标点击位置插入图片。由于是.net 8的Winform项目&#xff0c;选…

分布式数据库——HBase基本操作

启动HBase: 1.启动hadoop,进入hadoop的sbin中 cd /opt/hadoop/sbin/ 2.初始化namenode hdfs namenode -format 3.启动hdfs ./start-all.sh 4.启动hbase cd /opt/hbase/bin ./start-hbase.sh 5.使用jps查看进程 jps 以下图片则是hbase启动成功~ 运行HBase ./hbase sh…

“卷”智能, 从高质量算力开始

算力即国力&#xff0c;这已是产业共识。 当人工智能浪潮席卷全球之际&#xff0c;大家深刻感受到发展算力产业的重要性和紧迫性&#xff0c;高质量的人工智能算力已经与国家竞争、产业升级和企业转型息息相关。 去年&#xff0c;《算力基础设施高质量发展行动计划》的颁布&a…

PHP的guzzlehttp/guzzle库在碰到各种异常时的场景

PHP的guzzlehttp/guzzle库在碰到各种异常时的场景 结论: 经过测试得知 在http状态码为1xx, 2xx, 3xx时, 会在111处输出返回 在http状态码为4xx, 5xx时, 会在222处被捕获 在目标服务不可达或其他异常时会在333处被捕获 测试过程: 用其他程序写个接口, 实现输入什么状态码就返…

ICML 2024 论文分享┆一个简单且通用的交通预测提示调优框架

论文简介 本推文介绍了2024 ICML的优秀论文之一《FlashST: A Simple and Universal Prompt-Tuning Framework for Traffic Prediction》。论文的核心目标是通过整合空间和时间因素&#xff0c;精准地预测和分析交通流量的动态变化。然而&#xff0c;在交通预测领域&#xff0c…

解读 Story Protocol:IP 与区块链的潜力与障碍

撰文&#xff1a;100y.eth 编译&#xff1a;J1N&#xff0c;Techub News 8 月&#xff0c;据 The Block 报道&#xff0c;专注于知识产权&#xff08;IP&#xff09;的区块链 Story 宣布完成 a16z Crypto 领投 8000 万美元 B 轮融资&#xff0c;参投方包括 Polychain Capital&…

Nginx反向代理配置支持websocket

一、官方文档 WebSocket proxying 为了将客户端和服务器之间的连接从HTTP/1.1转换为WebSocket&#xff0c;使用了HTTP/1.1中可用的协议切换机制&#xff08;RFC 2616: Hypertext Transfer Protocol – HTTP/1.1&#xff09;。 然而&#xff0c;这里有一个微妙之处:由于“升级”…