LK2.两数相加
一、题目给你两个非空的链表表示两个非负的整数。它们每位数字都是按照逆序的方式存储的并且每个节点只能存储一位数字。请你将两个数相加并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外这两个数都不会以 0 开头。示例 1输入l1 [2,4,3], l2 [5,6,4]输出[7,0,8]解释342 465 807.示例 2输入l1 [0], l2 [0]输出[0]示例 3输入l1 [9,9,9,9,9,9,9], l2 [9,9,9,9]输出[8,9,9,9,0,0,0,1]提示每个链表中的节点数在范围[1, 100]内0 Node.val 9题目数据保证列表表示的数字不含前导零二、解题思路C:该代码通过模拟竖式加法的逻辑解决“两数相加”问题利用带头结点的单链表存储逆序整数在addTwoNumbers函数中通过while循环同步遍历两个输入链表将对应位数字与进位值相加取余数作为当前位结果并通过尾插法存入新链表同时更新进位值循环持续直到所有位处理完毕且无进位为止最终返回计算得到的新链表不过代码存在未判空即移动指针导致崩溃的隐患以及尾插效率低$O(N^2)$的问题建议增加指针非空判断并维护尾指针优化至 $O(N)$。JAVA:该解题思路以模拟手工加法运算为核心逐位处理两个逆序存储的链表链表节点对应数字的个位、十位、百位……首先初始化结果链表的头节点和尾节点为空进位值初始化为 0然后循环遍历两个链表的节点只要有一个链表未遍历完就继续分别获取当前节点值若节点为空则取 0计算两数之和并加上上一轮的进位接着根据结果链表是否为空创建首个节点或在尾节点后新增节点存储当前位结果和对 10 取余同时更新进位值和整除 10遍历完所有节点后若仍有剩余进位则在结果链表末尾新增存储该进位的节点最终返回结果链表的头节点完成两个数的加法运算。三、代码一CListLin.h文件#ifndef LINLIST_H #define LINLIST_H #include stdio.h #include malloc.h #ifndef DATATYPE #define DATATYPE typedef int DataType; #endif typedef struct Node{ DataType data; struct Node *next; }SLNode, *List; /** * brief 初始化单链表得到空链表 */ void ListInitiate(SLNode **head){ *head (SLNode*)malloc(sizeof(SLNode)); (*head)-next NULL; } /** * brief 求当前元素个数 * * return 返回链表长度元素个数 */ int ListLength(SLNode *head){ SLNode *phead-next; int size0; while(p){ size; pp-next; } return size; } /** * brief 插入元素在索引号为i的位置插入元素 * * param i 索引号取值范围为0~size-1索引号为i的元素结点是ai其逻辑序号为i1 * param x 待插入的元素值 * * return 状态码,0-错误,1-正常 */ int ListInsert(SLNode *head, int i, DataType x){ SLNode *p, *q; int j; //1.查找索引号为i-1的元素结点ai-1 phead; j-1; while(ji-1 p-next ! NULL){ j; pp-next; } //位置参数不正确 if(j!i-1){ printf(\n插入元素位置参数错); return 0; } //创建结点 q(SLNode *)malloc(sizeof(SLNode)); q-data x; q-next p-next; //插入结点 p-next q; return 1; } /** * brief 删除元素删除索引号为i的元素 * * param i 索引号取值范围为0~size-1索引号为i的元素结点是ai其逻辑序号为i1 * * return 状态码,0-错误,1-正常 */ int ListDelete(SLNode *head, int i, DataType *x){ SLNode *p, *s; int j;//逻辑序号 //链表为空链表时 if(head-nextNULL){ printf(\n链表为空链表没有元素可删除!); return 0; } //1.查找索引号为i-1的元素结点ai-1 phead; j-1; while(ji-1 p-next!NULL){ j; pp-next; } //位置参数不正确 if(j!i-1){ printf(\n删除元素位置参数错); return 0; } //2.保存结点的指针和元素值 sp-next; *xs-data; //3.删除结点脱链 p-nextp-next-next; //4.释放结点内存 free(s); return 1; } /** * brief 取元素 * * param i 索引号取值范围为0~size-1索引号为i的元素结点是ai其逻辑序号为i1 * * return 状态码,0-错误,1-正常 */ int ListGet(SLNode *head, int i, DataType *x){ SLNode *p; int j; //1.查找索引号为i的元素结点ai phead; j-1; while(ji p-next!NULL){ j; pp-next; } //位置参数不正确 if(j!i){ printf(\n取元素位置参数错); return 0; } //2.保存结点的元素值 *xp-data; return 1; } /** * brief 销毁单链表 */ void Destroy(SLNode **head){ SLNode *p,*q; p*head; while(p){ qp; //保存要释放的结点的指针 pp-next; //p指向后继结点 free(q); //释放结点 } *headNULL; //单链表的头指针不再指向任何结点 } /** * brief 显示单链表 */ //void Visit(DataType item) { // printf(%d , item); //} void ListDisplay(SLNode *head, void Visit(DataType item)){ SLNode *phead-next; //链表为空链表 if(!p){ printf(\n链表为空链表); return; } //输出单链表元素值 int i0; while(p){ if(i0){ printf(\n); }else{ printf( ); } i; //printf(%d,p-data); Visit(p-data); pp-next; } printf(\n); } ////尾插法 //void Insert(SLNode *head,DataType temp){ // if(head-nextNULL){ // return; // } // SLNode *p; // phead; // while(p-next!NULL){ // pp-next; // } // SLNode *s; // //创建结点 // s(SLNode *)malloc(sizeof(SLNode)); // s-datatemp; // s-nextNULL; // p-nexts; //} #endifLK2liangshuxiangjia.h文件#ifndef LK2LIANGSHUXIANGJIA_H #define LK2LIANGSHUXIANGJIA_H #include LinList.h //尾插法 void Insert(SLNode *head,DataType temp){ // if(head-nextNULL){ // return; // } SLNode *p; phead; while(p-next!NULL){ pp-next; } SLNode *s; //创建结点 s(SLNode *)malloc(sizeof(SLNode)); s-datatemp; s-nextNULL; p-nexts; } void Visit(DataType item) { printf(%d , item); } SLNode* addTwoNumbers(SLNode* l1, SLNode* l2) { int carry0; SLNode *result; ListInitiate(result); while(l1!NULL||l2!NULL||carry!0){ // 处理空链表为空则取值0 int val1 (l1 ! NULL) ? l1-data : 0; int val2 (l2 ! NULL) ? l2-data : 0; int sumval1val2carry; carrysum/10; int currentsum%10; Insert(result,current); // if(l1-datal2-data10){ // num1; // Insert(result,0); // } // else{ // Insert(result,l1-datal2-datanum); // num0; // } if (l1 ! NULL) l1 l1-next; if (l2 ! NULL) l2 l2-next; } return result; } #endifmain.c主函数文件#include stdio.h #include stdlib.h #includeLinList.h #includeLK2liangshuxiangjia.h int main(int argc, char *argv[]) { int l1[]{9,9,9,9,9,9,9}; int l2[]{9,9,9,9}; SLNode *temp1; SLNode *temp2; ListInitiate(temp1); ListInitiate(temp2); int lenth1sizeof(l1)/sizeof(l1[0]); int lenth2sizeof(l2)/sizeof(l2[0]); for(int i0;ilenth1;i){ Insert(temp1,l1[i]); } for(int j0;jlenth2;j){ Insert(temp2,l2[j]); } temp1temp1-next; temp2temp2-next; SLNode *readdTwoNumbers(temp1,temp2); ListDisplay(re,Visit); // 释放内存避免内存泄漏 Destroy(temp1); Destroy(temp2); Destroy(re); return 0; }二JAVAclass Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode head null, tail null; int carry 0; while (l1 ! null || l2 ! null) { int n1 l1 ! null ? l1.val : 0; int n2 l2 ! null ? l2.val : 0; int sum n1 n2 carry; if (head null) { head tail new ListNode(sum % 10); } else { tail.next new ListNode(sum % 10); tail tail.next; } carry sum / 10; if (l1 ! null) { l1 l1.next; } if (l2 ! null) { l2 l2.next; } } if (carry 0) { tail.next new ListNode(carry); } return head; } }四、测试示例 1输入l1 [2,4,3], l2 [5,6,4]输出[7,0,8]解释342 465 807.示例 2输入l1 [0], l2 [0]输出[0]示例 3输入l1 [9,9,9,9,9,9,9], l2 [9,9,9,9]输出[8,9,9,9,0,0,0,1]五、问题与解决问题 1空指针解引用会导致程序崩溃 Crash在 while 循环末尾l1 l1-next; l2 l2-next;场景当 l1 已经遍历完变为 NULL但 l2 还没完或者反之或者两者都完了但还有进位 carry。后果如果 l1 是 NULL执行 l1-next 会直接导致 Segmentation Fault (段错误)程序崩溃。修正只有当指针不为 NULL 时才能移动它。if (l1 ! NULL) l1 l1-next; if (l2 ! NULL) l2 l2-next;六、总结1.线性表的链式存储结构单链表节点定义使用struct定义包含数据域 (data) 和指针域 (next) 的节点理解指针自引用结构。带头结点 vs 不带头结点代码中使用了带头结点Dummy Head的初始化方式 (ListInitiate)理解了头结点在简化插入、删除操作及统一空表处理中的作用。指针操作熟练掌握指针的移动 (p p-next)、解引用 (p-data) 以及二级指针 (SLNode **head) 在修改头指针时的应用。2.动态内存管理内存分配使用malloc动态创建新节点理解堆内存的使用场景。内存释放通过Destroy函数遍历链表并free每个节点防止内存泄漏这是C语言编程的关键素养。空指针处理涉及NULL的判断理解野指针和空指针解引用的风险虽然你的代码中存在未判空即移动的Bug但这正是学习该知识点的反面教材。3.基本算法思想模拟法竖式加法模拟将数学中的“个位对齐、从低到高、逢十进一”逻辑转化为代码逻辑。边界条件处理不等长链表通过(l1 ! NULL) ? l1-data : 0处理两个加数位数不同的情况。最高位进位循环条件carry ! 0确保了最后产生的进位如 9110能被正确添加到结果链表末尾。4.模块化编程与文件组织头文件保护使用#ifndef ... #define ... #endif防止头文件重复包含。多文件协作将链表通用操作 (LinList.h)、特定业务逻辑 (LK2liangshuxiangjia.h) 和主程序 (main.c) 分离体现了良好的工程化思维。函数指针/回调思想ListDisplay函数接受void Visit(DataType item)作为参数展示了如何通过回调函数实现通用的遍历输出逻辑虽然这里只是简单打印但扩展性很强。5.时间复杂度与算法优化意识尾插法的效率陷阱你的Insert函数每次都需要从头遍历到尾部 ( O(N)O(N) )导致整体加法算法复杂度变为 O(N2)O(N2) 。这引出了维护尾指针 (tail)的重要性是将算法优化至 O(N)O(N) 的关键知识点。鲁棒性检查代码中暴露出的l1l1-next未判空问题是学习防御性编程和调试技巧如段错误排查的绝佳案例。

相关新闻

Flutter 三方库 test_api 的鸿蒙化适配指南 - 实现具备底层测试驱动与自定义匹配器扩展的质量基石架构、支持端侧测试骨架深度定制实战

Flutter 三方库 test_api 的鸿蒙化适配指南 - 实现具备底层测试驱动与自定义匹配器扩展的质量基石架构、支持端侧测试骨架深度定制实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net Flutter 三方库 test_api 的鸿蒙化适配指南 - 实现具备底层测试驱动与自定义匹配器扩展的质量基石架构、支持端侧测试骨架深度定制实战 前言 在进行 Flutter for OpenHarmony 的大规模测试…

2026/5/17 11:55:47 阅读更多 →
汇川中型PLC分期付款程序:PLC时间读取与设置、随机滚动码解加密及触摸屏模板程序

汇川中型PLC分期付款程序:PLC时间读取与设置、随机滚动码解加密及触摸屏模板程序

汇川AM中型PLC程序,汇川IT7000系列触摸屏程序 自己写的设备分期付款程序,汇川中型PLC_分期付款程序 1、包含PLC时间的读取与设置。 2、使用随机滚动码计算解加密(3天、7天、1个月、三个月、半年、一年、永久解除灵活设置)。 3、包含标准的触摸…

2026/5/17 11:55:43 阅读更多 →
Flutter 组件 ical 适配鸿蒙 HarmonyOS 实战:标准日历解析,构建全场景跨平台日程同步与时间管理枢纽

Flutter 组件 ical 适配鸿蒙 HarmonyOS 实战:标准日历解析,构建全场景跨平台日程同步与时间管理枢纽

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net Flutter 组件 ical 适配鸿蒙 HarmonyOS 实战:标准日历解析,构建全场景跨平台日程同步与时间管理枢纽 前言 在鸿蒙(OpenHarmony)生态迈向高效…

2026/5/17 11:55:42 阅读更多 →

最新新闻

深入pytest_collection_modifyitems钩子:定制化测试用例执行与调度

深入pytest_collection_modifyitems钩子:定制化测试用例执行与调度

1. 项目概述如果你在用pytest做自动化测试,尤其是项目规模稍微大一点,或者对测试报告、用例执行顺序有特殊要求时,你大概率会碰到一个绕不开的“神器”——pytest_collection_modifyitems钩子函数。我第一次深入使用它,是因为一个…

2026/7/3 22:17:57 阅读更多 →
DVWA从入门到精通(八):SQL Injection(SQL注入)

DVWA从入门到精通(八):SQL Injection(SQL注入)

摘要:本文是《DVWA从入门到精通》系列的第八篇,带你全面掌握SQL Injection(SQL注入)模块的攻防全流程。从SQL注入的核心原理出发,逐步讲解Low、Medium、High三个级别的攻击手法与源码分析,并深入探讨Imposs…

2026/7/3 22:17:57 阅读更多 →
基于PIC18F4685与KMR221的高精度电压管理系统设计

基于PIC18F4685与KMR221的高精度电压管理系统设计

1. 项目概述:基于KMR221与PIC18F4685的电压管理系统在嵌入式系统设计中,精确的电压管理一直是硬件工程师面临的挑战。传统方案往往需要复杂的分立元件组合,而现代微控制器与专用电源管理芯片的协同工作正在改变这一局面。这次我要分享的&…

2026/7/3 22:15:57 阅读更多 →
【Bug已解决】Anthropic tool_result 找不到对应 tool use id 解决方案

【Bug已解决】Anthropic tool_result 找不到对应 tool use id 解决方案

【Bug已解决】Anthropic tool_result 找不到对应 tool use id 解决方案 1. 问题描述 在自己动手用 Anthropic Messages API 搭建 Agent Harness、实现多轮工具调用循环时,很多人会在某一次请求时遇到这样的 400 错误: {"type": "error&qu…

2026/7/3 22:13:56 阅读更多 →
Linux下fastai第一课完整实操:PyTorch+CUDA+Jupyter环境从零搭建

Linux下fastai第一课完整实操:PyTorch+CUDA+Jupyter环境从零搭建

1. 项目概述:在Linux系统上扎实走完fastai第一课的完整实操路径我带过不少从零开始学深度学习的朋友,发现一个特别普遍的现象:很多人卡在“环境跑不起来”这一步,不是报错就是版本冲突,最后对着Jupyter Notebook里那一…

2026/7/3 22:11:56 阅读更多 →
双检测时代论文修改怎么选?10 款主流降重复降 AIGC 工具分层测评,paperxie 领跑定稿适配赛道

双检测时代论文修改怎么选?10 款主流降重复降 AIGC 工具分层测评,paperxie 领跑定稿适配赛道

paperxie-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/科研绘图降重复率 - PaperXie智能写作PaperXie免费论文查重检测-首款免费论文检测软件,为毕业生提供专业的论文重复率检测、论文降重、Aigc检测、智能排版 、论文写作等一站式服务。https://www.paperxie.c…

2026/7/3 22:11:56 阅读更多 →

日新闻

Nginx防御TLS重协商攻击实战:从原理到配置与监控

Nginx防御TLS重协商攻击实战:从原理到配置与监控

1. 项目概述:为什么TLS重协商攻击至今仍需警惕十多年前的CVE-2011-1473,一个关于TLS/SSL协议重协商机制的漏洞,现在提起来还有必要吗?很多运维和开发朋友可能会觉得,这都老掉牙了,现代服务器和客户端不都默…

2026/7/3 0:03:59 阅读更多 →
华为防火墙双通道远程管理实战:Web与SSH配置详解

华为防火墙双通道远程管理实战:Web与SSH配置详解

1. 项目概述:为什么需要双通道远程管理防火墙?在任何一个稍具规模的企业网络里,防火墙都是那个默默守护在边界的关键角色。作为网络工程师,我们不可能每次都跑到机房,插上console线去配置它。远程管理能力,…

2026/7/3 0:03:59 阅读更多 →
AD74413R与PIC18F65K40的高精度工业数据采集方案

AD74413R与PIC18F65K40的高精度工业数据采集方案

1. 项目概述:AD74413R与PIC18F65K40的协同工作在工业自动化和精密测量领域,同时实现高精度模数转换(ADC)和数模转换(DAC)功能是许多复杂系统的核心需求。AD74413R作为一款四通道可配置模拟输入/输出器件,与PIC18F65K40微控制器的组合&#xf…

2026/7/3 0:05:59 阅读更多 →

周新闻

月新闻