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

【刷题汇总--大数加法、 链表相加(二)、大数乘法】

C++日常刷题积累

  • 今日刷题汇总 - day006
    • 1、大数加法
      • 1.1、题目
      • 1.2、思路
      • 1.3、程序实现
    • 2、 链表相加(二)
      • 2.1、题目
      • 2.2、思路
      • 2.3、程序实现
    • 3、大数乘法
      • 3.1、题目
      • 3.2、思路
      • 3.3、程序实现
    • 4、题目链接

今日刷题汇总 - day006

1、大数加法

1.1、题目

在这里插入图片描述

1.2、思路

读完题,明白大数相加,通常采用字符串的模式,是为了解决int等类型大数相加超出范围的应用, 那么让思考模拟实现数字字符串的加法运算. 那么,要实现加法运算,很快能想到将字符串的每一位都转为数字计算求和,最后再转回字符串返回不就行了吗? 那么,需要求得两个字符串的长度len1和len2,然后同样采用预处理,一位一位的处理,即个位相加,所以定义一个变量carry表示个位相加后的进位,定义一个变量sum表示个位上的和,那么求sum的个位就是需要返回的字符串retstr的个位数字了.依次循环直到len1和len2都计算结束后,得到了累加和的retstr字符串,但是我们直接尾插属于是得到的逆置的结果,而需要的结果是需要正序的,所以还可以利用reverse逆置retstr字符串才是我们需要的结果.此外,在逆置之前,我们还需要判断,最后进位上是否已经加上(如示例1的情况),如果没加则继续尾插字符’1’ ,否则,直接逆置即可.接下来,就是程序实现.

1.3、程序实现

首先,根据思路,求得len1和len2两个数字字符串的长度, 然后定义retstr最后要返回的字符串,继续定义进位变量carry, 定义sum个位上的和,定义尾插到retstr的个位结果数individual变量.

#include <iterator>
class Solution {
public:string solve(string s, string t){int len1 = s.size()- 1;int len2 = t.size() -1;string retstr;retstr.reserve(len1 > len2 ? len1 + 2:len2 + 2);int carry = 0;int sum = 0;int individual = 0;return retstr;}
};

接着,处理数字字符串的相加,思考不难知道while的条件是需要一直处理到较长字符串结束才行,所以需用 | | 运算,然后,分别转换两个字符串的个位字符为数字,保存到变量value1和value2中,然后求和得到sum,注意记得加上carry才行(因为循环第二趟,如果sum不加上进位是计算不正确的哈),然后将求到的sum十位数字保存在carry就是个位求和所得的进位,同理,求sum的个位individual 就是需要尾插到retstr的返回结果的数字,依次类推,直到两个字符串全部加完,这里巧妙的使用三目运算符解决较短字符串加完后,长字符串继续加时,短字符串累加就是置为0进行相加. 此外, 注意字符元素 - '0’转化为数字,尾插时需要individual + ‘0’转回字符.最后,判断一下进位是否为空,否则继续尾插一个字符’ 1’即可.由于retstr是尾插操作,所以我们需要的结果,利用reverse逆置一下再返回结果即可.

#include <iterator>
class Solution {
public:string solve(string s, string t){int len1 = s.size()- 1;int len2 = t.size() -1;string retstr;int carry = 0;int sum = 0;int individual = 0;while(len1 >= 0 || len2 >= 0){int value1 = len1 >= 0 ? s[len1--] - '0' : 0;int value2 = len2 >= 0 ? t[len2--] - '0' : 0;sum = value1 + value2 + carry;carry = sum /10 ;individual = sum % 10;retstr += individual + '0';}if(carry){retstr += '1';}reverse(retstr.begin(),retstr.end());return retstr;}
};

在这里插入图片描述
此外,还能够利用reserve提前开辟好空间.

#include <iterator>
class Solution {
public:string solve(string s, string t){int len1 = s.size()- 1;int len2 = t.size() -1;string retstr;retstr.reserve(len1 > len2 ? len1 + 2:len2 + 2);int carry = 0;int sum = 0;int individual = 0;while(len1 >= 0 || len2 >= 0){int value1 = len1 >= 0 ? s[len1--] - '0' : 0;int value2 = len2 >= 0 ? t[len2--] - '0' : 0;sum = value1 + value2 + carry;carry = sum /10 ;individual = sum % 10;retstr += individual + '0';}if(carry){retstr += '1';}reverse(retstr.begin(),retstr.end());return retstr;}
};

在这里插入图片描述

在这里插入图片描述

2、 链表相加(二)

2.1、题目

在这里插入图片描述

2.2、思路

读完题, 知道跟上道题类似的,只不过要求让我们利用链表完成数字的加法运算. 然后返回运算完成后的链表,注意的是这里是单链表,而加法是从低位向高位作加法运算的.不过不像上道题可以调用库中封装好的reverse, 所以得想办法自己写一个逆置链表的函数,逆置后再用带头的链表retListhead 作为返回结果的链表和工作指针retcur 模拟头插, 循环实现个位上的加法求和sum, 再依然像上道题一样采用进位和头插个位individual到retListhead 链表中, 其中值得注意的是,利用带头的链表方便操作,所以不管是逆置操作还是最后返回结果链表之前都需要释放头结点,从第一个节点处返回即可.那么接下来,就是程序实现.

2.3、程序实现

首先,按照题目思路分析的需求,封装一个逆置函数reverse, 那么为了方便使用带头的链表newhead ,然后利用cur工作指针遍历需要逆置的链表, 遍历一个头插一个到newhead即可, 因为是链表的常规操作,只需要注意一下最后返回前释放头结点, 返回第一个节点处,另外就是利用nextnode保留原链表的下一个节点,否则cur回不去原链表继续遍历, 且注意链表的指向顺序, 由于是单链表所以先改后面的指向再改前面的指向,否则先改前面的指向会导致自己指向自己就属于无用功,错误操作了.为了方便理解,简单画个图:
在这里插入图片描述

/*** struct ListNode {*	int val;*	struct ListNode *next;*	ListNode(int x) : val(x), next(nullptr) {}* };*/
class Solution
{
public:ListNode* reverse(ListNode* head){ListNode* newhead = new ListNode(0);ListNode* cur = head;while(cur){ListNode* nextnode = cur->next;cur->next = newhead->next;newhead->next = cur;cur = nextnode;}cur = newhead->next;delete newhead;return cur;}ListNode* addInList(ListNode* head1, ListNode* head2){head1 = reverse(head1);head2 = reverse(head2);}
};

完成了逆置链表, 就像上道题一样需要知道链表的长度, 这里利用cur1和cur2工作指针,直到较长的链表加完为止,所以用 || 运算, 接着定义需要返回的链表retListhead和它的工作指针retcur, 为了方便头插所以使用的带头的,最后释放掉就行了, 然后定义sum这里用于求和和进位控制, 由于是个位一位一位的作加法运算,所以sum/=10就是得到的进位, 一起放入while进行或运算, 有进位就再头插一次即可, 接着就是跟上道题没什么区别的逻辑了.写好函数体,最后释放头结点,将返回的链表逆置后返回即可.

/*** struct ListNode {*	int val;*	struct ListNode *next;*	ListNode(int x) : val(x), next(nullptr) {}* };*/
class Solution
{
public:ListNode* reverse(ListNode* head){ListNode* newhead = new ListNode(0);ListNode* cur = head;while(cur){ListNode* nextnode = cur->next;cur->next = newhead->next;newhead->next = cur;cur = nextnode;}cur = newhead->next;delete newhead;return cur;}ListNode* addInList(ListNode* head1, ListNode* head2){head1 = reverse(head1);head2 = reverse(head2);ListNode* cur1 = head1;ListNode* cur2 = head2;ListNode* retListhead = new ListNode(0);ListNode* retcur = retListhead;int sum = 0;int individual = 0;while(cur1 || cur2 || sum){if(cur1){sum += cur1->val;cur1 = cur1->next;}if(cur2){sum += cur2->val;cur2 = cur2->next;}individual = sum % 10;retcur = retcur->next = new ListNode(individual);sum /= 10;}retcur = retListhead->next;retListhead->next = nullptr;delete retListhead;retcur = reverse(retcur);return retcur;}
};

在这里插入图片描述

在这里插入图片描述

3、大数乘法

3.1、题目

在这里插入图片描述

3.2、思路

读完题,知道这类题也跟第一题一样属于解决数值太大超出范围时的一种应用题型. 让我们实现用数字字符串模拟乘法的效果, 并以字符串的形式返回即可. 那么,说着是乘法, 肯定要以化繁为简的思想去思考, 通过推导和验证发现, 可以把乘法换算成加法的运算,具体可以画个图演示一下:
在这里插入图片描述
首先根据示意图可以看出:
(1). 字符串的下标是逆置的,作运算需要先逆置;
(2). 依次相乘后, 结果行result等于绿色加蓝色;
(3). 然后对结果行的高位作为进位, 对结果行取模得到的个位数作为最后的结果返回即可.
其次, 结果数组result的大小最大是两个字符串的长度之和,如上图就是3+2 = 5, 即 result[m+n] .另外还需要注意题目中示例2具有前导0的情况, 那么接下来就是程序实现.

3.3、程序实现

首先根据思路的分析程序就大致分为以下几步:
(1). 逆置字符串和求字符串长度为运算和确定reslut数组做准备;
(2). 开辟result结果求和数组,并套两层for循环求得结果放入数组中,注意此时数组得到的结果仍然是逆置的;
(3). 处理结果数组中的个位进行尾插与十位进位的问题;
(4). 处理前导0的情况;
(5). 最后逆置retstr字符串返回即可.

那么先逆置字符串, 才好进行运算.再求字符串的长度,保存到变量m和n, 然后就可以确定开辟结果数组result的大小了, 然后,按照思路分析的蓝色和绿色进行相乘求和运算保存到result数组中.为了好理解还是在之前图的例子中, 画个图理解result[i+j]的作用:
在这里插入图片描述

#include <algorithm>
class Solution
{
public:string solve(string s, string t){reverse(s.begin(),s.end());reverse(t.begin(),t.end());int m = s.size();int n = t.size();vector<int> result(m+n);for(int i = 0;i < m;i++){for(int j = 0; j < n;j++){result[i+j] += (s[i] - '0')*(t[j] - '0');}}}
};

接着, 处理结果数组中的个位进行尾插与十位进位的问题;先定义一个变量carry表示进位,再定义一个restr需要返回的字符串,准备进行尾插, 然后遍历数组执行取模即个位进行尾插即可,套路跟前两道题都类似,只是要注意遍历结束后由于还可能存在进位的数未处理,如上图中的最高位2,需要额外判断再尾插进去即可.

#include <algorithm>
class Solution
{
public:string solve(string s, string t){reverse(s.begin(),s.end());reverse(t.begin(),t.end());int m = s.size();int n = t.size();vector<int> result(m+n);for(int i = 0;i < m;i++){for(int j = 0; j < n;j++){result[i+j] += (s[i] - '0')*(t[j] - '0');}}int carry = 0;string retstr;for(auto ch : result){carry += ch;retstr += carry%10 + '0';carry /= 10;}while(carry){retstr += carry%10 + '0';carry /= 10;}}
};

最后,就是处理前导0的情况,且保存末尾的0,值得注意的是因为是逆置所以判断是判断尾巴即back处的字符,然后pop掉多余的0,然后逆置retstr字符串返回即可.

#include <algorithm>
class Solution
{
public:string solve(string s, string t){reverse(s.begin(),s.end());reverse(t.begin(),t.end());int m = s.size();int n = t.size();vector<int> result(m+n);for(int i = 0;i < m;i++){for(int j = 0; j < n;j++){result[i+j] += (s[i] - '0')*(t[j] - '0');}}int carry = 0;string retstr;for(auto ch : result){carry += ch;retstr += carry%10 + '0';carry /= 10;}while(carry){retstr += carry%10 + '0';carry /= 10;}while(retstr.size() > 1 && retstr.back() == '0'){retstr.pop_back();}reverse(retstr.begin(), retstr.end());return retstr;}
};

在这里插入图片描述
在这里插入图片描述

4、题目链接

大数加法
链表相加(二)
大数乘法

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 在原有的iconfont.css文件中加入新的字体图标
  • 【OnlyOffice】桌面应用编辑器,插件开发大赛,等你来挑战
  • Qt提升控件失败的解决办法
  • PCDN技术如何提高内容分发效率?(贰)
  • vue3长列表优化,使用vue-virtual-scroller实现直播间弹幕列表虚拟滚动效果
  • VitePress美化
  • webSocket网页通信---使用js模拟多页面实时通信
  • Flink,spark对比
  • Python爬虫之什么是逆向工程?逆向是什么?
  • 实现原理:远程过程调用(RPC)
  • Postman编写测试脚本
  • mybatis-plus参数绑定异常
  • 解析Java中1000个常用类:Date类,你学会了吗?
  • 【Unity2D 2022:Particle System】添加命中粒子特效
  • React 中 useEffect
  • hexo+github搭建个人博客
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 「译」Node.js Streams 基础
  • Django 博客开发教程 8 - 博客文章详情页
  • JavaScript DOM 10 - 滚动
  • jdbc就是这么简单
  • Lucene解析 - 基本概念
  • Mithril.js 入门介绍
  • 关于for循环的简单归纳
  • 回流、重绘及其优化
  • 聊一聊前端的监控
  • 线性表及其算法(java实现)
  • 小程序button引导用户授权
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • #NOIP 2014# day.1 T2 联合权值
  • $forceUpdate()函数
  • (2)leetcode 234.回文链表 141.环形链表
  • (第30天)二叉树阶段总结
  • (第一天)包装对象、作用域、创建对象
  • (二)hibernate配置管理
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (三) diretfbrc详解
  • (实测可用)(3)Git的使用——RT Thread Stdio添加的软件包,github与gitee冲突造成无法上传文件到gitee
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • **PHP分步表单提交思路(分页表单提交)
  • .Net Core 生成管理员权限的应用程序
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .net6 当连接用户的shell断掉后,dotnet会自动关闭,达不到长期运行的效果。.NET 进程守护
  • .NET技术成长路线架构图
  • [ vulhub漏洞复现篇 ] struts2远程代码执行漏洞 S2-005 (CVE-2010-1870)
  • [AIGC] Java 和 Kotlin 的区别
  • [AIGC] Redis基础命令集详细介绍
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [ASP.NET 控件实作 Day7] 设定工具箱的控件图标
  • [BZOJ4554][TJOI2016HEOI2016]游戏(匈牙利)
  • [C#] 基于 yield 语句的迭代器逻辑懒执行