算法竞赛小白晋级之路---高精度减法(题目+解析+代码)

1.高精度减法

下面的这个是来自于洛谷上面的题目:

2.代码实现

下面的这个是具体的代码,我认为还是有点复杂的,简单的看一下吧:

cpp 复制代码
#include <iostream>

using namespace std;

const int N = 1e6 + 10;

int a[N], b[N], c[N];
int la, lb, lc;

// 比大小
bool cmp(string& x, string& y)
{
    // 先比较长度
    if(x.size() != y.size()) return x.size() < y.size();

    // 再按照 字典序 的方式比较
    return x < y;
}

// 高精度减法的模板 - c = a - b
void sub(int c[], int a[], int b[])
{
    for(int i = 0; i < lc; i++)
    {
        c[i] += a[i] - b[i]; // 对应位相减,然后处理借位
        if(c[i] < 0)
        {
            c[i + 1] -= 1; // 借位
            c[i] += 10;
        }
    }

    // 处理前导零
    while(lc > 1 && c[lc - 1] == 0) lc--;
}

int main()
{
    string x, y; cin >> x >> y;

    // 比大小
    if(cmp(x, y))
    {
        swap(x, y);
        cout << '-';
    }

    // 1. 拆分每一位,然后逆序放在数组中
    la = x.size(); lb = y.size(); lc = max(la, lb);
    for(int i = 0; i < la; i++) a[la - i - 1] = x[i] - '0';
    for(int i = 0; i < lb; i++) b[lb - i - 1] = y[i] - '0';

    // 2. 模拟减法的过程
    sub(c, a, b); // c = a - b
    
    // 输出结果
    for(int i = lc - 1; i >= 0; i--) cout << c[i];

    return 0;
}

1)我觉得在这个问题里面可以抓住两条主线:相较于我们的这个高精度的加法的主线;

第一点:变化的是什么,没有变化的是什么;

第二点:我们的这个减法里面的主要模块的划分;

2)先来谈谈这个第一点的主线,变化的是什么,这个里面多了cmp函数,因为需要保证这个事大数减去小数,不变的就是我们的这个思路是不变的,还是字符串转换成为数组倒序的存放到我们的这个对应的数组里面去,然后进行这个位数的处理过程;

3)首先看一下这个第一大模块,就是这个sub方法,或者叫做函数,这个里面的swap实际上就是想要保证这个事大数据减去小数据,仅此而已,这个需要先去判断这个位数,位数不一样的话,直接根据这个位数多的确定大小即可;

位数一样的时候,按照这个字典序进行比较即可,如果需要进行交换,说明这个本来说是小数减去大数,因此这个cmp判断里面有这个cout负号的过程,这个就是为了保证我们的这个绝对值不变,但是这个负号需要改变,这个是数学知识,我不想多去赘述;

4)sub函数是这个代码里面的核心和我们的这个加法里面的add函数类似,注意这个里面的+=,这个和我们的高精度加法里面的这个事类似的,然后这个if事在判断我们的这个借位情况,比如这个类似于2-8之类的情况,我们需要进行借位,但是这个需要判断,只有两个数据相减出现负数的时候才说明这个需要借位;

5)借位的时候就是前面的这个c[i+1]减去1即可,不要问我这个为什么是i+1,因为这个顺序和我们的这个字符串里面的这个顺序是相反的,大家自己去理解一下,我点到为止;

6)然后就是这个0的处理,我们的加法运算里面是这个高位的进位处理;

减法里面是0的处理。例如我们的997-995,这个时候计算之后就是002,但是这个高位的0显然是不需要进行输出的,因此这个需要保证我们的这个指针lc指向的是我们的这个结果里面的第一个非零的数据,也就是我们的这个while里面的c[lc-1]的判断条件;

但是还有一个情况,例如我们的999-999,这个时候就是000,这个时候我们是需要输出结果的,因此这个事需要保留一个0的,也就是我们的这个while条件里面的这个lc>1的情况,只有当这两个条件同时满足的时候,这个代码才会执行;

也就是我们的这个数据有位数,而且这个前一位是0,我们才会进行这个lc--的处理;

7)变化之中找不变,进行对比总结,我认为才是正确的学习之道;

相关推荐
地平线开发者4 小时前
理想汽车智驾方案介绍专题 1 端到端+VLM 方案介绍
算法·自动驾驶
地平线开发者5 小时前
征程 6 | UCP 任务优先级/抢占简介与实操
算法·自动驾驶
杰克尼5 小时前
912. 排序数组
算法
jndingxin6 小时前
OpenCV直线段检测算法类cv::line_descriptor::LSDDetector
人工智能·opencv·算法
秋说6 小时前
【PTA数据结构 | C语言版】阶乘的递归实现
c语言·数据结构·算法
小指纹6 小时前
巧用Bitset!优化dp
数据结构·c++·算法·代理模式·dp·bitset
爱Java&Java爱我8 小时前
数组:从键盘上输入10个数,合法值为1、2或3,不是这三个数则为非法数字,试编辑统计每个整数和非法数字的个数
java·开发语言·算法
是店小二呀9 小时前
【算法-BFS 解决最短路问题】探索BFS在图论中的应用:最短路径问题的高效解法
算法·图论·宽度优先
qq_513970449 小时前
力扣 hot100 Day46
算法·leetcode
满分观察网友z10 小时前
递归与迭代的优雅之舞:我在评论区功能中悟出的“树”之道(104. 二叉树的最大深度)
后端·算法