复习leetcode第二题:两数相加

本文会给出笔者自己的解答(代码较为冗余,其实就是屎山代码)以及优秀代码的解析

下图是题目

b98ab95f90244322a1a09ac50efca748.png

解法1(笔者所使用的办法): 

解题思路:

以下思路是基于示例1(上图)思考的

步骤1:因为该函数只传来了两个链表的首元结点指针,所以我们不难想到可以创建一个新链表来存放两链表相加的内容

步骤2:由于我们最后需要返回新链表的首元结点指针,而新链表不断创建以后,用于创建链表的指针也后移了,因此我们还需要创建一个指针phead,用作最后的函数返回

步骤3:题目给我们的结构体名称为Listnode(在注释行写了),笔者觉得大小写切换太麻烦了,因此这边改成了listnode

步骤4:通过示例1我们也不难发现,我们需要使用循环语句来多次让两个链表的结点内容相加,并存放到新链表中;而循环的退出条件应该是l1链表和l2链表的所有结点的数据全部相加完了,即l1、l2同时为空指针

上述步骤代码如下:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode listnode;
listnode* buynode(int x) //用于创建新链表的函数{listnode* newnode = (listnode*)malloc(sizeof(listnode));newnode->val = x;newnode->next = NULL;return newnode;
}//l1首元结点指针      //l2首元结点指针
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) 
{int count=0;listnode* newnode=buynode(0); //创建一个新链表的首元结点,之后每次创建新链表都传0值,因为只有给新链表结点0这个初值才不会影响结果//当然也并不是必须给新链表的结点赋初值,这里只是为了保险起见listnode* phead=newnode;while(l1||l2) //退出条件为两个指针全为空指针{……;}return phead;
}

1f08a6952a6c4ca58a8f0183ef310a4c.png

示例1的情况:

示例1中出现了两数相加等于10的情况,最后l1、l2结点所对应的新链表结点留下来的数据为0,然后把 1这个数值 进1位和后续结点数据内容相加,这也就导致了 4+3+1 = 8。但我们不难发现,l1、l2的结点数据相加最大值为18(即使加上1也只有19),因此只有可能把1这个数值进1位,不可能把1以外的数值进1位。 

因此我们可以进行一个分支语句,分为了最后l1、l2结点数据相加 大于等于10 小于等于9两种情况;然后通过一个计数器count,来判断是否需要对后一个结点数据加1

每次相加完,让l1、l2、新链表都往后移动一位

代码如下所示:

 

        //分为l1+l2 <=9 以及 l1+l2 >=10 两种情况//<=9if((l1->val)+(l2->val)+count<=9) {newnode->val=(l1->val)+(l2->val)+count;count=0;}//>=10else{newnode->val=(l1->val)+(l2->val)+count-10;count=1;}l1=l1->next;l2=l2->next; newnode->next=buynode(0);newnode=newnode->next;

bcd5c9e8d2374ad2af6f20353d02538e.png

示例2的情况用示例1的代码就能解决,此处不再讲解。

f6607e7e89c5422dbc8b24a36c825832.png

示例3的情况:

该示例告诉我们,l1为空时,l2不一定为空;l2为空时,l1不一定为空。

因此,会有三种情况:分别是l1、l2都不为空,只有l1为空,只有l2为空。此处可以通过三条分支语句来解决。

当l1为空,l2不为空时,把l1继续往后移动一位代码会出错(对空指针进行解引用操作),因此我们需要在不同的分支语句里面对不同情况进行不同的向后移位操作

而当把所有数据相加完,l1、l2都为空的时候,有可能count仍为1(示例3输出里最后会出现一个1的原因),因此我们需要在整个循环语句后,解决这个问题。直接在新链表最后面加上一个结点,且最后一个结点数据域只可能为1(上文已经讲解过只可能为1的原因)

代码如下所示:

 

        if(l1&&l2) //两指针都非空{//分为l1+l2 <=9 以及 l1+l2 >=10 两种情况//<=9if((l1->val)+(l2->val)+count<=9) {newnode->val=(l1->val)+(l2->val)+count;count=0;}//>=10else{newnode->val=(l1->val)+(l2->val)+count-10;count=1;}l1=l1->next;l2=l2->next; }else if(l1) //l1还不为空的情况{if((l1->val)+count<=9){newnode->val=(l1->val)+count;count=0;}else{newnode->val=(l1->val)+count-10;count=1;}l1=l1->next; //为防止对空指针l2进行解引用操作}    else if(l2) //l2还不为空的情况{if((l2->val)+count<=9){newnode->val=(l2->val)+count;count=0;}else{newnode->val=(l2->val)+count-10;count=1;}l2=l2->next; //为防止对空指针l1进行解引用操作}  if(count==1) //两个指针全都为空但count还是为1,是对示例3的解决{newnode->next=buynode(1); //直接在newnode指针最后面加上一个结点,且最后一个结点数据域只可能为1}  

由于新链表一直要创建到l1、l2都为空,那么在循环语句(循环语句退出条件为l1、l2都为空)里的新链表创建就不需要加以限制了呢?

答:如果不加以限制,会出现下图的情况,这是由于在最后一次l1、l2结点数据相加并放入新链表以后,还会再进行一次新链表的结点创建

解决方法:

  1. 把新链表的首元结点的创建放在循环语句里面,并且在第一次创建新链表的结点时,把该结点赋给phead,并且所有操作都放在l1、l2结点数据相加之前
  2. 在循环语句末尾,给新链表的创建加上一条if语句,当l1、l2全为空指针,不再进行结点创建工作(笔者在此使用的)

4a886befb54f41dcb16ffdaa555f483c.png

        if(l1||l2) //只有两指针还有需要存入的数据再开辟新的空间,如果都已经存放完毕,那么就无需再开辟新的{newnode->next=buynode(0);newnode=newnode->next;}

解法1全部代码展示:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode listnode;
listnode* buynode(int x){listnode* newnode = (listnode*)malloc(sizeof(listnode));newnode->val = x;newnode->next = NULL;return newnode;
}//l1首元结点指针      //l2首元结点指针
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) 
{int count=0;listnode* newnode=buynode(0); //创建一个新链表的首元结点listnode* phead=newnode;while(l1||l2) //退出条件为两个指针全为空{if(l1&&l2) //两指针都非空{//分为l1+l2 <=9 以及 l1+l2 >=10 两种情况//<=9if((l1->val)+(l2->val)+count<=9) {newnode->val=(l1->val)+(l2->val)+count;count=0;}//>=10else{newnode->val=(l1->val)+(l2->val)+count-10;count=1;}l1=l1->next;l2=l2->next; }else if(l1) //l1还不为空的情况{if((l1->val)+count<=9){newnode->val=(l1->val)+count;count=0;}else{newnode->val=(l1->val)+count-10;count=1;}l1=l1->next; //为防止对空指针l2进行解引用操作}    else if(l2) //l2还不为空的情况{if((l2->val)+count<=9){newnode->val=(l2->val)+count;count=0;}else{newnode->val=(l2->val)+count-10;count=1;}l2=l2->next; //为防止对空指针l1进行解引用操作}    if(l1||l2) //只有两指针还有需要存入的数据再开辟新的空间,如果都已经存放完毕,那么就无需再开辟新的{newnode->next=buynode(0);newnode=newnode->next;}}if(count==1) //两个指针全都为空但count还是为1,是对示例3的解决{newnode->next=buynode(1); //直接在newnode指针最后面加上一个结点,且最后一个结点数据域只可能为1}return phead;
}

1eb04a4521f04ef3be2c8e8d44f01e2a.png


解法2(优秀代码):
 

下面的代码是leetcode官方给的C语言题解,好漂亮的代码!

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {struct ListNode *head = NULL, *tail = NULL;int carry = 0;while (l1 || l2) {int n1 = l1 ? l1->val : 0;int n2 = l2 ? l2->val : 0;int sum = n1 + n2 + carry;if (!head) {head = tail = malloc(sizeof(struct ListNode));tail->val = sum % 10;tail->next = NULL;} else {tail->next = malloc(sizeof(struct ListNode));tail->next->val = sum % 10;tail = tail->next;tail->next = NULL;}carry = sum / 10;if (l1) {l1 = l1->next;}if (l2) {l2 = l2->next;}}if (carry > 0) {tail->next = malloc(sizeof(struct ListNode));tail->next->val = carry;tail->next->next = NULL;}return head;
}

上述代码解释:

官方题解也是通过创建一个新链表,然后解决问题

首先创建了两个指针,一个指向了首元结点(用作返回),一个指向了尾元结点(用作存放数据);carry和我代码中的count一样,都是保存多出来的那个1的

循环语句退出条件、分支语句的写法此处省略

l1 ? l1->val : 0 --->该操作符的作用:l1不为空指针,就留下l1的值;l1为空指针,就留下0

l2 ? l2->val : 0 --->作用同上

sum:就是l1、l2的结点数据(还有carry)相加后结果

!head:如果头指针为空指针为真(首元结点的创建,和首元结点地址的保留)

sum%10:对10取余

sum/10:整型相除

进行完对新链表的赋值操作以后,让新链表的尾元结点指针指向空指针,等待下一次使用

最后如果carry依旧为1,那么再开辟一个结点空间存放,最后返回head指针

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/19526.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年终端安全管理系统最新排名(2024终端安全管理软件TOP5)

在2024年&#xff0c;随着企业数字化转型的加速和网络安全威胁的日益严峻&#xff0c;终端安全管理系统的重要性愈发凸显。终端作为企业数据交互的关键节点&#xff0c;其安全性直接关系到企业的运营和数据的完整性。因此&#xff0c;各大终端安全管理系统厂商纷纷推出新的产品…

基于Vue+Node.js的购物网站设计与实现-计算机毕业设计源码28500

摘 要 近年来&#xff0c;随着移动互联网的快速发展&#xff0c;电子商务越来越受到网民们的欢迎&#xff0c;电子商务对国家经济的发展也起着越来越重要的作用。简单的流程、便捷可靠的支付方式、快捷畅通的物流快递、安全的信息保护都使得电子商务越来越赢得网民们的青睐。现…

数据库系统概念(第七周 第一堂)(E-R模型)

目录 前言 基本概念 观点与模型 作用与要求 E-R模型元素 实体&#xff08;entity&#xff09; 实体集&#xff08;entity set&#xff09; 属性&#xff08;attribute&#xff09; 域&#xff08;domain&#xff09; 码 &#xff08;key&#xff09; 联系 &#x…

虚拟现实环境下的远程教育和智能评估系统(五)

查阅相关VR眼动注意力联合教育学相关论文 1.Exploring Eye Gaze Visualization Techniques for Identifying Distracted Students in Educational VR&#xff08;IEEE VR 2020&#xff09; 摘要&#xff1a;我们提出了一种架构&#xff0c;使VR教学代理能够响应眼动追踪监控…

Android HIDL接口添加

一.HIDL介绍 HIDL的全称是HAL interface definition language&#xff08;硬件抽象层接口定义语言&#xff09;&#xff0c;是Android Framework 与Android HAL之间的接口。HIDL 旨在用于进程间通信 (IPC)&#xff0c;进程之间的通信 采用 Binder 机制。 二.HIDL 与AIDL 的对…

JVM之【运行时数据区1】

JVM简图 运行时数据区简图 一、程序计数器&#xff08;Program Counter Register&#xff09; 1.程序计数器是什么&#xff1f; 程序计数器是JVM内存模型中的一部分&#xff0c;它可以看作是一个指针&#xff0c;指向当前线程所执行的字节码指令的地址。每个线程在执行过程中…

Python魔法之旅-魔法方法(04)

目录 一、概述 1、定义 2、作用 二、主要应用场景 1、构造和析构 2、操作符重载 3、字符串和表示 4、容器管理 5、可调用对象 6、上下文管理 7、属性访问和描述符 8、迭代器和生成器 9、数值类型 10、复制和序列化 11、自定义元类行为 12、自定义类行为 13、类…

Tensorflow入门实战 P02-彩色图片分类

目录 1、序言 2、主要代码 3、运行结果展示 &#xff08;1&#xff09;展示cifar10里面的20张图片 &#xff08;2&#xff09;预测的图片 &#xff08;3&#xff09;模型评估 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K…

水经微图PC版4.3.10发布

让GIS更简单高效&#xff0c;让地图更丰富及时&#xff01; 水经微图&#xff08;以下简称“微图”&#xff09;新版已上线&#xff0c;在该版本中主要新增了天地图历史影像查看功能&#xff0c;以及其它功能的优化。 当前版本 当前版本号为&#xff1a;4.3.10 如果你发现该…

Pytorch反向传播算法(Back Propagation)

一&#xff1a;revise 我们在最开始提出一个线性模型。 x为我们的输入&#xff0c;w为权重。相乘的结果是我们对y的预测值。 那我们在训练时就是对这个权重w进行更新&#xff0c;就需要用到上一章提到的梯度下降算法&#xff0c;不断更新w。但是此时注意不是用y的预测值对w进…

linux centos nfs挂载两台服务器挂载统一磁盘目录权限问题

查看用户id id 用户名另一台为 修改uid和gid为相同id&#xff0c;添加附加组 usermod -u500 -Gwheel epms groupmod -g500 epms

网络协议。

一、流程案例 接下来揭秘我要说的大事情&#xff0c;“双十一”。这和我们要讲的网络协议有什么关系呢&#xff1f; 在经济学领域&#xff0c;有个伦纳德里德&#xff08;Leonard E. Read&#xff09;创作的《铅笔的故事》。这个故事通过一个铅笔的诞生过程&#xff0c;来讲述…

[代码复现]Self-Attentive Sequential Recommendation(ing)

参考代码&#xff1a;SASRec.pytorch 可参考资料&#xff1a;SASRec代码解析 前言&#xff1a;文中有疑问的地方用?表示了。可以通过ctrlF搜索’?。 环境 conda create -n SASRec python3.9 pip install torch torchvision因为我是mac运行的&#xff0c;所以device是mps 下面…

算法(七)插入排序

文章目录 插入排序简介代码实现 插入排序简介 插入排序&#xff08;insertion sort)是从第一个元素开始&#xff0c;该元素就认为已经被排序过了。然后取出下一个元素&#xff0c;从该元素的前一个索引下标开始往前扫描&#xff0c;比该值大的元素往后移动。直到遇到比它小的元…

【C语言】探索文件读写函数的全貌

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 &#x1f525;引言 本章将介绍文件读取函数的相关知识和展示使用场景&am…

React组件通信——兄弟组件

兄弟组件通信 方法一&#xff1a;状态提升 子组件先将数据传递到父组件&#xff0c;父组件再把数据传到另一个子组件中。 import { useState } from "react"; // 定义A组件&#xff0c;向B组件发送数据 function A({ onGetMsg }) {const name "this is A na…

fyne apptab布局

fyne apptab布局 AppTabs 容器允许用户在不同的内容面板之间切换。标签要么只是文本&#xff0c;要么是文本和一个图标。建议不要混合一些有图标的标签和一些没有图标的标签。 package mainimport ("fyne.io/fyne/v2/app""fyne.io/fyne/v2/container"//&…

PolarDB分布式架构学习笔记

PolarDB分布式是什么&#xff1f; 业务场景有哪些&#xff1f; 分布式焦点问题&#xff1f; 技术架构 CN DN介绍 CDC组件介绍 Columnar组件介绍 视频学习&#xff1a;PolarDB 实操课 第一讲&#xff1a;PolarDB分布式版架构介绍_哔哩哔哩_bilibili

都在说的跨网文件共享系统是什么?企业该怎么甄选?

跨网文件共享系统成为越来越受关注的产品焦点&#xff0c;那么跨网文件共享系统是什么呢&#xff1f;跨网文件共享是指在不同网络之间共享文件的过程&#xff0c;使得不同网络中的用户可以访问和使用共享的文件。 原则上而言&#xff0c;不同网络间的文件是无法共享的&#xff…

OAK相机如何将 YOLOv9 模型转换成 blob 格式?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是Ashely。 专…