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; } }