算法通关村 —— 数组实现加法专题

目录

数组实现加法专题

1 数组实现整数加法

2 字符串加法

3 二进制加法


数组实现加法专题

加法题目有很多种,比如让你用数组来表示一个数,如何实现加法呢?这时和如果按照正常加法运算,即从数组末尾向前挨着计算,但是实现的时候会发现许多问题,例如算到A[0] 位置发现还要进位那该怎么办呢?
再比如,给定两个数,一个用数组存储,一个是普通的正数,又该如何处理呢?

再或者,如果两个整数是用字符串表示呢?又如果是二进制的加法呢?问题有很多,但其实解题思路并不难,可以说就是一个模板,让我们一起来学习吧

1 数组实现整数加法

先看一个用数组实现逐个加一的问题。具体要求如下:由整数组成的非空数组所表示的非负整数,在此基础上加一。这里最高位数字存放在数组的首位,数组中每个元素只存储单个数字。并且假设除了整数 0 之外,这个整数不会以零开头。例如:

输入:digits = [1, 2, 4]
输出:[1, 2, 5]

看起来是不是很简单,只需要从最后开始加1, 如果有进位就标记以下,依次往前家去。但是如果到头了还要进位那怎么办呢。例如digits = [9,9,9,9], 从后向前加时,到A[0] 的位置计算为0,需要再次进位但是数组长度是确定的,不能保存了,那怎么办呢。

这里关键点在于,什么时候会出现这种情况,只有一种情况,就是一定要有9, 99,999,9999……这样都是9的结构,加上1后结果又都是10,100,1000……。所以结果首位为1,其他位位0。到这里就很简单了,我们只需要申请一个空间比A大一个长度的数组B,然后把B[0] 设置为1即可,其他位置就默认为0了,这样代码就非常的简洁,具体实现如下:

class Solution {
    public int[] plusOne(int[] digits) {
        int len = digits.length;
        for(int i = len-1; i >= 0; i--){
            // 最后一位+1
            digits[i]++;
            // 加1后除10取余做为最后一位
            digits[i] %= 10;
            if(digits[i] != 0) return digits; // 不为0则直接返回
        }
        // 如果数组长度不够,新建一个长度加一的数组,第一位为1,其他位默认为0
        digits = new int[len+1];
        digits[0] = 1;
        return digits;
    }
}

2 字符串加法

如果将数字保存在字符串中呢。也就是用字符串来表示数字,然后计算它们的和。具体要求如下:给定两个字符串形式的非负整数 num1 和 num2,计算它们的和并以字符串形式返回。不能使用任何内建的用于处理大整数的库(例如BigInteger) , 也不能直接将输入的字符串转换为整数形式。

例如:
输入:num1 = "123", num2 = "88"
输出:"211"

我们平时具体加法规则为:从低到高诸位相加,如果当前位超过10,则向高位进一位。

因此我们只需定义两个指针分别指向两字符串的末尾,即最低位,同时定义一个变量来维护当前是否有进位,然后从末尾到开头诸位相加即可。

这里需要解决一个问题,如果两个数字位数不同该如何处理?很简单,若遍历到某位没有数字,只需补0计算即可,具体实现看下面代码:

class Solution {
    public String addStrings(String a, String b) {
        // 定义两个从末尾开始遍历的指针和进位变量add
        int i = num1.length() - 1, j = num2.length() - 1, add = 0;
        StringBuilder ans = new StringBuilder();
        while(i >= 0 || j >= 0 || add >0){     
            int x = i >= 0 ? a.charAt(i) - '0' : 0;
            int y = j >= 0 ? b.charAt(j) - '0' : 0;
            int res = x + y + add
            ans.append(res % 10); // 将余数添加到结果
            add = res / 10; // 除以10结果作为进位数
            i--; j--;
        }
        return ans.reverse().toString(); // 反转字符串
    }
}

3 二进制加法

继续来看,如果是二进制字符串又该如何处理呢?示例如下:

输入:a = "11", b = "1"
输出:"100"

我们来看,这不还是字符串加法嘛,所以和十进制二进制有没有关系?一点没有,只不过进位时十进制是对10进行计算判断是否需要进位,而二进制是对2而已。

在处理最后的结果是否需要进一位时,有以下两种处理方式:

1)和十进制一样,在进行计算时直接拼接字符串,得到一个反向字符,最后再翻转

2)最后如果有进位,则直接在前方进行字符串拼接添加进位,这里用到了第二种实现

所以我们直接来看代码实现:

class Solution {
    public String addBinary(String a, String b) {
        StringBuilder ans = new StringBuilder();
        int ca = 0; // 进位数
        for(int i = a.length()-1, j = b.length() - 1; i >= 0 || j >= 0; i--, j--){
            int sum = ca;
            sum += i >= 0 ? a.charAt(i) - '0' : 0;
            sum += j >= 0 ? b.charAt(j) - '0' : 0;
            ans.append(sum % 2); // 将余数添加到结果
            ca = sum / 2; // 除以2结果作为进位数
        }
        ans.append(ca == 1 ? ca : ""); // 若最后结果为1需要进位则结果再添加1位
        return ans.reverse().toString(); // 反转字符串
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值