BM86题解 | #大数加法#
大数加法
https://www.nowcoder.com/practice/11ae12e8c6fe48f883cad618c2e81475
解法一:BigInteger
有库调库。
import java.util.*;
import java.math.*;
public class Solution {
public String solve (String s, String t) {
BigInteger bigs = new BigInteger(s);
BigInteger bigt = new BigInteger(t);
return (bigs.add(bigt)).toString();
// 减法同理
// return (bigs,subtract(bigt)).toString()
}
}
解法二:官方题解双指针
先特殊条件判断,如果有一条是空串,返回另一条就行
然后创建一个长串等长的char型数组便于操作
双指针等长,分别从两个串的末尾向前遍历,模拟数字相加,从后向前方便处理进位
注意:由于是char[ ]类型,所以每次都要转换成数值类型
s.charAt(i) - '0'
两个字符做减运算,底层其实进行的是Unicode运算
eg: '3' 的Unicode是51, '0'的Unicode是48,'3' - '0' = 3 是个数值类型,这样就可以用于数值计算
i下标从后往前,j下表也从后往前,因为两条串可能不等长, 尾端对齐只是一个概念上的,对于下标而言还是头部对齐的,所以我们使用 i - (两条串长度的差) = j 与 i 对应的位置
如果短串没有遍历完就一直遍历
如果短串遍历完了就处理一下最后的进位,再直接返回长串即可
本题没有只使用了一个for循环控制长串,而短串则是在for中使用if来进行分支。
这样做的好处就是短串遍历完了之后,长串仍然可能有多次遍历,因为存在99999+1这种需要连续进位的情况
最后当i也遍历完了,存在一种特殊情况就是还需要进一位
这种情况就不能在char型数组上处理了,因为char[ ]定长,没法增一位
我们可以使用最朴素的方法:字符串拼接,把最终的char[ ]转换成String,再 '1' + String即可
import java.util.*;
public class Solution {
public String solve (String s, String t) {
if (s.equals("") || s.length() == 0) return t;
if (t.equals("") || t.length() == 0) return s;
// 让s为长串,t为短串,方便后续统一在s上操作
if (s.length() < t.length()) {
String temp = s;
s = t;
t = temp;
}
// 用于进位
int carry = 0;
char[] res = s.toCharArray();
// 从后往前遍历,如果短串遍历完了,就结算进位后直接返回长串即可
for (int i = s.length() - 1; i >= 0; --i) {
// 转成int类型,然后加上进位
// 字符与数字都是使用unicode编码,减去'0'实际上是在执行字符编码之间的数值运算。
// eg: '3' - '0'其实是 51 - 48 = 3,也就是当前的数字
int num = s.charAt(i) - '0' + carry;
// 把短串对应的下标j求到
int j = i - (s.length() - t.length());
// 如果短串还没遍历完
if (j >= 0) {
// 开始计算
num += t.charAt(j) - '0';
}
// 当前数字处理进位,如果有就是1,没有就是0
carry = num / 10;
// 取10的模,把进位给抹掉(如果有),剩下的个位数作为i位置的值
num %= 10;
// 最后转回字符的时候记得把'0'的unicode加回来,这时候还是一个int,加一个(char)强转
res[i] = (char)(num + '0');
}
String fin = new String(res);
// 结算最后可能的进位,因为已经到字符串了,直接拼接就行
if (carry == 1) {
fin = "1" + fin;
}
return fin;
}
}

