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

news2025/2/26 2:54:42

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、题目链接

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

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

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

相关文章

react 项目中预防xss攻击的插件 dompurify

一、安装 $ yarn add dompurify $ yarn add --dev types/dompurify 二、使用 import DOMPurify from dompurify;// 1、处理&#xff1a; DOMPurify.sanitize(htmlContent)// 2、之后放进 dangerouslySetInnerHTML dangerouslySetInnerHTML{{ __html: cleanHTML }} 如&#…

【IT领域新生必看】 Java编程中的重载(Overloading):初学者轻松掌握的全方位指南

文章目录 引言什么是方法重载&#xff08;Overloading&#xff09;&#xff1f;方法重载的基本示例 方法重载的规则1. 参数列表必须不同示例&#xff1a; 2. 返回类型可以相同也可以不同示例&#xff1a; 3. 访问修饰符可以相同也可以不同示例&#xff1a; 4. 可以抛出不同的异…

经典双运算放大器LM358

前言 LM358双运放有几十年的历史了吧&#xff1f;通用运放&#xff0c;很常用&#xff0c;搞电路的避免不了接触运放&#xff0c;怎么选择运放&#xff0c;是工程师关心的问题吧&#xff1f; 从本文开始&#xff0c;将陆续发一些常用的运放&#xff0c;大家选型可以参考&#…

win10使用小技巧一

1. 查看电脑IP地址 步骤&#xff1a;按WinR打开运行框 → 输入cmd点确定 → 输入ipconfig回车 → 查看IP地址。 2. 解决网页文字不能复制 步骤&#xff1a;按F12 → 调试框里点击设置 → 向下滑找到 禁用 JavaScript → 勾选 → 复制文字。 3. 解决电脑不能上网 方法一&…

第10章 项目总结02:针对当前项目的面试题

1 项目概况 1.1 项目介绍 从以下几个方面进行项目介绍&#xff1a; 1、项目的背景&#xff1a;做什么业务、服务的客户群是谁、谁去运营、自研还是外包等问题。 2、项目的业务流程&#xff1a;课程发布流程、断点续传流程、视频处理流程、认证授权流程、支付流程、CI/CD流程…

SpringBoot新手快速入门系列教程:基于JPA的一个Mysql简单读写例子

现在我们来做一个简单的读写Mysql的项目 1&#xff0c;先新建一个项目&#xff0c;我们叫它“HelloJPA”并且添加依赖 2&#xff0c;引入以下依赖&#xff1a; Spring Boot DevTools (可选&#xff0c;但推荐&#xff0c;用于开发时热部署)Lombok&#xff08;可选&#xff0c…

cs224n作业4

NMT结构图&#xff1a;&#xff08;具体结构图&#xff09; LSTM基础知识 nmt_model.py&#xff1a; 参考文章&#xff1a;LSTM输出结构描述 #!/usr/bin/env python3 # -*- coding: utf-8 -*-""" CS224N 2020-21: Homework 4 nmt_model.py: NMT Model Penchen…

ElasticSearch 如何计算得分及一个不太成熟的使用

1.背景 最近在做 ES 相关东西&#xff0c;只最会在查询的时候给不同的字段设置不同的权重&#xff0c;但是得分具体怎么算的不太明白&#xff0c;花了4-5 天研究和总结了一下。这样不至于被别人问到“这个分数怎么算出来的&#xff1f;”&#xff0c;两眼一抹黑&#xff0c;不…

【C++】模板进阶--保姆级解析(什么是非类型模板参数?什么是模板的特化?模板的特化如何应用?)

目录 一、前言 二、什么是C模板&#xff1f; &#x1f4a6;泛型编程的思想 &#x1f4a6;C模板的分类 三、非类型模板参数 ⚡问题引入⚡ ⚡非类型模板参数的使用⚡ &#x1f525;非类型模板参数的定义 &#x1f525;非类型模板参数的两种类型 &#x1f52…

【Unity2D 2022:Particle System】添加命中粒子特效

一、创建粒子特效游戏物体 二、修改粒子系统属性 1. 基础属性 &#xff08;1&#xff09;修改发射粒子持续时间&#xff08;Duration&#xff09;为1s &#xff08;2&#xff09;取消勾选循环&#xff08;Looping&#xff09; &#xff08;2&#xff09;修改粒子存在时间&…

Vue表单输入绑定v-model

表单输入绑定 在前端处理表单时&#xff0c;我们常常需要将表单输入框的内容同步给Javascript中相应的变量。手动连接绑定和更改事件监听器可能会很麻&#xff0c;v-model 指令帮我们简化了这一步骤。 <template><h3>表单输入绑定</h3><hr> <inpu…

推荐Bulk Image Downloader插件下载网页中图片链接很好用

推荐&#xff1a;Bulk Image Downloader chome浏览器插件下载图片链接&#xff0c;很好用。 有个网页&#xff0c;上面放了数千的gif的电路图&#xff0c;手工下载会累瘫了不可。想找一个工具分析它的静态链接并下载&#xff0c;找了很多推荐的下载工具&#xff0c;都是不能分…

docker部署mycat,连接上面一篇的一主二从mysql

一、docker下载mycat镜像 查看安装结果 这个名称太长&#xff0c;在安装容器时不方便操作&#xff0c;设置标签为mycat docker tag longhronshens/mycat-docker mycat 二、安装容器 先安装一个&#xff0c;主要目的是获得配置文件 docker run -it -d --name mycat -p 8066:…

算法系列--分治排序|再谈快速排序|快速排序的优化|快速选择算法

前言:本文就前期学习快速排序算法的一些疑惑点进行详细解答,并且给出基础快速排序算法的优化版本 一.再谈快速排序 快速排序算法的核心是分治思想,分治策略分为以下三步: 分解:将原问题分解为若干相似,规模较小的子问题解决:如果子问题规模较小,直接解决;否则递归解决子问题合…

【JVM 的内存模型】

1. JVM内存模型 下图为JVM内存结构模型&#xff1a; 两种执行方式&#xff1a; 解释执行&#xff1a;JVM是由C语言编写的&#xff0c;其中有C解释器&#xff0c;负责先将Java语言解释翻译为C语言。缺点是经过一次JVM翻译&#xff0c;速度慢一点。JIT执行&#xff1a;JIT编译器…

java自旋锁

Java自旋锁&#xff08;Spin Lock&#xff09;是一种用于多线程同步的锁机制&#xff0c;通过反复检查某个条件&#xff08;通常是一个共享变量的状态&#xff09;而不是挂起线程来实现锁的获取。自旋锁的核心思想是让线程在尝试获取锁时保持活动状态&#xff0c;即进行“自旋”…

KBPC3506-ASEMI储能专用整流桥KBPC3506

编辑&#xff1a;ll KBPC3506-ASEMI储能专用整流桥KBPC3506 型号&#xff1a;KBPC3506 品牌&#xff1a;ASEMI 封装&#xff1a;KBPC-4 正向电流&#xff08;Id&#xff09;&#xff1a;35A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;600V 正向浪涌电流&#xf…

进程控制-exec函数

让父子进程来执行不相干的操作 能够替换进程地址空间的代码.text段 执行另外的程序&#xff0c;不需要创建额外的的地址空间 当前程序中调用另外一个应用程序 指定执行目录下的程序 int execl(const char *path, const char *arg&#xff0c;/* (char *) NULL */); /* pat…

【MindSpore学习打卡】应用实践-自然语言处理-基于RNN的情感分类:使用MindSpore实现IMDB影评分类

情感分类是自然语言处理&#xff08;NLP&#xff09;中的一个经典任务&#xff0c;广泛应用于社交媒体分析、市场调研和客户反馈等领域。本篇博客将带领大家使用MindSpore框架&#xff0c;基于RNN&#xff08;循环神经网络&#xff09;实现一个情感分类模型。我们将详细介绍数据…

数据结构之“栈”(全方位认识)

&#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;数据结构 前言 栈是一种数据结构&#xff0c;具有" 后进先出 "的特点 或者也可见说是 ” 先进后出 “。大家一起加油吧冲冲冲&#xff01;&#xff01; …