程序员崩溃瞬间:这4道链表题不会,面试直接凉凉?速补!!

程序员崩溃瞬间:这4道链表题不会,面试直接凉凉?速补!!
坚持用清晰易懂的图解+多语言代码,让每道题变得简单! 🌟
🚀呆头个人主页详情
🌱呆头个人Gitee代码仓库
📌 呆头详细专栏系列
座右铭:“不患无位,患所以立。”

👨‍💻 程序员崩溃瞬间:这4道链表题不会,面试直接凉凉?速补!!


前言

🚀 你好,欢迎来到《编程闯关记》!
这里是算法与数据结构的实战基地,也是你从“暴力解法”到“最优解”的进化场。

🔍 专栏初衷

  • 清晰的图解 + 多语言代码(Python/Java/C++/C),拆解每道题背后的逻辑。
  • 不只讲“怎么做”,更讲“为什么”——从题目分析、边界条件到复杂度优化。
  • 适合想夯实基础突击面试的你,尤其针对LeetCode/牛客高频题!

💡 如何使用本专栏
1️⃣ 先独立思考:尝试自己写出第一版代码(哪怕很烂)。
2️⃣ 对比解法:看看我的思路和你的差异,吸收优化技巧。
3️⃣ 举一反三:每篇末尾会附相似题目链接,趁热打铁。

📌 坚持打卡
算法没有捷径,但正确的方法能让你少走弯路。每天15分钟,和我一起用代码雕刻思维!

(正文开始👇)


目录

1.移除链表元素

力扣链接直达<请点击

在这里插入图片描述

方法思路

这个C语言实现采用了创建新链表的方式来处理删除操作,主要步骤如下:

  1. 初始化新链表:使用newHeadnewTail指针来构建新链表
  2. 遍历原链表:使用pCur指针遍历原链表
  3. 节点筛选
    • 如果节点值不等于目标值,将其加入新链表
    • 如果节点值等于目标值,释放该节点内存
  4. 处理链表末尾:确保新链表的末尾指向NULL
  5. 返回新链表头节点

代码实现

/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */structListNode*removeElements(structListNode* head,int val){structListNode* newHead =NULL;// 新链表的头structListNode* newTail =NULL;// 新链表的尾structListNode* pCur = head;// 遍历原链表的指针while(pCur !=NULL){if(pCur->val != val){// 如果当前节点不需要删除,加入新链表if(newHead ==NULL){ newHead = newTail = pCur;}else{ newTail->next = pCur; newTail = newTail->next;} pCur = pCur->next;}else{// 如果当前节点需要删除,跳过并释放内存structListNode* toDelete = pCur; pCur = pCur->next;free(toDelete);}}// 确保新链表的末尾指向NULL(防止原链表末尾有残留指针)if(newTail !=NULL){ newTail->next =NULL;}return newHead;}

代码解释

  1. 初始化指针
    • newHeadnewTail初始化为NULL,用于构建新链表
    • pCur初始化为原链表头节点,用于遍历
  2. 链表遍历
    • 使用while循环遍历整个链表
    • 对每个节点判断其值是否等于目标值
  3. 节点处理
    • 保留节点:当节点值不等于目标值时,将其加入新链表
      • 如果是第一个保留的节点,同时设置newHeadnewTail
      • 否则追加到newTail后面
    • 删除节点:当节点值等于目标值时
      • 保存要删除的节点指针
      • 移动pCur到下一个节点
      • 释放当前节点内存
  4. 链表收尾
    • 确保新链表的最后一个节点的next指向NULL
    • 防止原链表末尾有不需要的指针
  5. 返回结果
    • 返回新链表的头节点指针

这种方法的时间复杂度是O(n),空间复杂度是O(1),是一种高效且内存安全的实现方式。

2.反转链表

力扣链接直达<请点击

在这里插入图片描述

方法思路

这段代码实现了链表的反转操作,采用迭代法进行反转。主要步骤如下:

  1. 初始化指针
    • prev:指向已经反转部分的链表头,初始为NULL
    • pnext:临时保存下一个节点的指针
    • pcur:当前正在处理的节点,初始为链表头
  2. 迭代过程
    • 保存当前节点的下一个节点(pnext = pcur->next
    • 将当前节点的next指针指向前一个节点(完成反转)
    • 移动prevpcur指针继续处理下一个节点
  3. 终止条件
    • pcur为NULL时,表示已处理完所有节点

代码实现

/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */typedefstructListNode ListNode;structListNode*reverseList(structListNode* head){ ListNode* prev =NULL; ListNode* pnext =NULL; ListNode* pcur = head;while(pcur !=NULL){ pnext = pcur->next;// 保存下一个节点 pcur->next = prev;// 反转当前节点的指针 prev = pcur;// 前驱节点移动到当前节点 pcur = pnext;// 移动到下一个节点}return prev;// 返回新的链表头}

代码解释

  1. 指针初始化
    • prev初始化为NULL,表示反转后的链表初始为空
    • pcur初始化为head,从链表头开始处理
  2. 反转过程
    • 每次迭代中,首先保存当前节点的下一个节点(pnext
    • 然后将当前节点的next指针指向prev,完成反转
    • 最后移动prevpcur指针继续处理后续节点
  3. 返回值
    • 循环结束时,prev指向原链表的最后一个节点,即反转后的新链表头
    • 因此返回prev作为反转后的链表头

3.查找链表中间结点

力扣链接直达<请点击

在这里插入图片描述

方法思路

这段代码实现了查找链表中间节点的功能,采用了快慢指针法(也称为"龟兔赛跑"算法)。主要步骤如下:

  1. 边界条件处理:如果链表为空,直接返回NULL
  2. 初始化指针
    • fast快指针(每次移动两步)
    • slow慢指针(每次移动一步)
  3. 遍历链表
    • 快指针每次移动两步
    • 慢指针每次移动一步
  4. 终止条件
    • 当快指针到达链表末尾时,慢指针正好指向中间节点

代码实现

/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */typedefstructListNode ListNode;structListNode*middleNode(structListNode* head){if(head ==NULL)// 处理空链表情况returnNULL;else{ ListNode* fast = head;// 快指针 ListNode* slow = head;// 慢指针while(fast !=NULL&& fast->next !=NULL){ fast = fast->next->next;// 快指针每次移动两步 slow = slow->next;// 慢指针每次移动一步}return slow;// 返回中间节点}}

代码解释

  1. 边界检查
    • 首先检查链表是否为空(head == NULL
    • 如果是空链表,直接返回NULL
  2. 快慢指针初始化
    • 快指针fast和慢指针slow都初始化为链表头节点
  3. 遍历过程
    • 快指针每次移动两步(fast = fast->next->next
    • 慢指针每次移动一步(slow = slow->next
    • 循环继续的条件是快指针及其下一个节点都不为NULL
  4. 返回值
    • 当快指针到达链表末尾时,慢指针正好指向中间节点
    • 返回慢指针指向的节点
奇数长度链表:快指针到达最后一个节点时,慢指针正好在中间例如:1→2→3→4→5,慢指针停在3偶数长度链表:快指针超过末尾时,慢指针停在第二个中间节点例如:1→2→3→4,慢指针停在3(题目通常要求这种结果)

4.合并两个有序链表

力扣链接直达<请点击

在这里插入图片描述

方法思路

这段代码实现了合并两个有序链表的功能,采用迭代方法进行合并。主要步骤如下:

  1. 边界条件处理
    • 如果其中一个链表为空,直接返回另一个链表
  2. 初始化合并链表
    • 确定合并后链表的头节点(两个链表头中较小的那个)
  3. 迭代合并
    • 比较两个链表当前节点的值
    • 将较小值的节点连接到合并链表
  4. 处理剩余节点
    • 将未遍历完的链表剩余部分连接到合并链表末尾

代码实现

/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */typedefstructListNode ListNode;structListNode*mergeTwoLists(structListNode* list1,structListNode* list2){// 处理空链表的情况if(list1 ==NULL)return list2;if(list2 ==NULL)return list1; ListNode* head =NULL;// 合并后链表的头节点 ListNode* tail =NULL;// 合并后链表的尾节点// 确定头节点(取两个链表头中较小的)if(list1->val <= list2->val){ head = list1; list1 = list1->next;}else{ head = list2; list2 = list2->next;} tail = head;// 合并剩余节点while(list1 !=NULL&& list2 !=NULL){if(list1->val <= list2->val){ tail->next = list1; list1 = list1->next;}else{ tail->next = list2; list2 = list2->next;} tail = tail->next;}// 连接剩余节点if(list1 !=NULL){ tail->next = list1;}else{ tail->next = list2;}return head;}

代码解释

  1. 边界检查
    • 检查两个链表是否为空,若其中一个为空则直接返回另一个
  2. 初始化合并链表
    • 比较两个链表头节点的值,选择较小的作为合并后链表的头节点
    • 移动被选中链表的指针到下一个节点
  3. 迭代合并过程
    • 比较两个链表当前节点的值
    • 将较小值的节点连接到合并链表的尾部
    • 移动相应链表的指针和合并链表的尾指针
  4. 处理剩余节点
    • 当其中一个链表遍历完后,将另一个链表的剩余部分直接连接到合并链表末尾
  5. 返回值
    • 返回最初确定的合并链表头节点

你说得对,我需要更清楚地解释这段代码的工作原理。让我们深入分析这个"连接剩余节点"的操作:

为什么不需要循环就能连接所有剩余节点?

关键在于理解链表的特性。当 while 循环结束时(即 list1 == NULL || list2 == NULL),此时:

  1. 链表节点已经是有序的:在之前的循环中,我们已经按顺序连接了所有较小的节点
  2. 剩余节点本身就是有序的:因为输入链表本来就是有序的
  3. 只需要一次连接:剩余未处理的节点已经按顺序连接在一起

Read more

英伟达GTC 2026大会开幕:AI智能体时代正式到来,黄仁勋发布新一代推理芯片与Rubin架构

英伟达GTC 2026大会开幕:AI智能体时代正式到来,黄仁勋发布新一代推理芯片与Rubin架构

导读:北京时间3月16日,全球AI行业的目光聚焦圣何塞。英伟达创始人黄仁勋在GTC 2026大会主题演讲中,正式宣告AI产业从“造模型”迈入“用模型”的新纪元,发布了新一代推理芯片与Rubin架构,并推出对标OpenAI的AI智能体平台。这场科技盛宴不仅揭示了未来三年的技术方向,更将直接影响千行百业的数字化转型进程。 核心新闻摘要 时间:2026年3月16日(北京时间) 事件:英伟达GTC 2026大会在加州圣何塞正式开幕,黄仁勋发表了长达两小时的主题演讲。 核心发布: * 新一代推理芯片:性能较上一代提升50%,功耗降低30%,专门针对AI智能体、大规模推理场景优化。同时推出了更便宜的入门级AI芯片,旨在降低中小企业使用AI的门槛。 * Rubin架构GPU(R100/R200系列):基于3nm工艺与HBM4内存,性能实现代际跃升,聚焦AI工厂与物理AI应用。 * AI智能体平台:对标OpenAI,支持工业制造、办公文档、智能家居等多场景的自主任务执行,能够自主学习用户习惯,优化交互体验。 * 开源大模型圆桌讨论:黄仁勋亲自主持,邀请Perplexity创始人Ar

By Ne0inhk

SpringBoot详解

文章目录 * 概览 * 与Spring的区别 * 创建SpringBoot项目 * SpringBoot常用注解 * SpringBoot自动配置 * @SpringBootConfiguration * @EnableAutoConfiguration * SpringBoot配置管理 * SpringBoot嵌入式服务器 * SpringBoot测试 概览 SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。SpringBoot提供了一种新的编程范式,可以更加快速便捷地开发Spring项目,在开发过程当中可以专注于应用程序本身的功能开发,而无需在Spring配置上花太大的工夫。 SpringBoot基于Sring4进行设计,继承了原有Spring框架的优秀基因。SpringBoot准确的说并不是一个框架,而是一些类库的集合。maven或者gradle项目导入相应依赖即可使用 SpringBoot,而无需自行管

By Ne0inhk

OpenClaw gateway start 报 401 Invalid API key?一个环境变量的坑

今天折腾了半小时,终于搞明白为什么 openclaw gateway start 一直报 HTTP 401: Invalid API key,而 openclaw gateway run 却能正常工作。 记录一下,免得以后又踩。 问题现象 用 openclaw gateway run 前台运行,一切正常,能正常对话。 但换成 openclaw gateway start(systemd 后台服务),就报错: HTTP 401: Invalid API key 明明配置文件里 API key 写得好好的,为什么会这样? 原因分析 run 和 start 的区别: * run — 前台运行,

By Ne0inhk
OpenClaw Gateway 安装失败:systemctl --user is-enabled unavailable 排查与解决(完整踩坑记录)

OpenClaw Gateway 安装失败:systemctl --user is-enabled unavailable 排查与解决(完整踩坑记录)

说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除 作者:zhu6201976 最近在安装 OpenClaw Gateway 时,遇到了一个比较奇怪的错误: systemctl is-enabled unavailable Command failed: systemctl --user is-enabled openclaw-gateway.service 看起来只是一个简单的 systemd 错误,但实际上背后涉及: * systemd user service * Node.js / nvm 环境 * PATH 环境变量 * CLI daemon 启动方式 这篇文章记录了 完整的排查过程 + 最终解决方案。 一、运行环境 我的环境如下: Window11 + WSL2 Ubuntu 24.04.4

By Ne0inhk