题目
对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组。例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]。
给定非负整数 X 的数组形式 A,返回整数 X+K 的数组形式。
示例 1:
输入:A = [1,2,0,0], K = 34
输出:[1,2,3,4]
解释:1200 + 34 = 1234
示例 2:
输入:A = [2,7,4], K = 181
输出:[4,5,5]
解释:274 + 181 = 455
示例 3:
输入:A = [2,1,5], K = 806
输出:[1,0,2,1]
解释:215 + 806 = 1021
示例 4:
输入:A = [9,9,9,9,9,9,9,9,9,9], K = 1
输出:[1,0,0,0,0,0,0,0,0,0,0]
解释:9999999999 + 1 = 10000000000
提示:
1 <= A.length <= 10000
0 <= A[i] <= 9
0 <= K <= 10000
如果 A.length > 1,那么 A[0] != 0
解题思路
首先排除将数组A转化为int或者long形式,因为A.lenth <= 10000,也就是说A所代表的整型数字最大位数可能有10000个,远超int/long int 所能表示范围。
考虑将K转化为数组形式,然后A+K就成了2个数组按位加(需进位)的问题。
这里可能会存在2个问题:
1.不确定A、K长度;
2.高位溢出;
因为最终和值长度不确定,可以用链表存储按位相加的和值(顺序表只适合在尾部插入数据),并且每次都将插到头部,这样生成的和值列表按序号递增,存储位的位权递减。
实现代码
从个位到高位,分别对2个整数进行遍历求和(注意进位)。
/**
* 从个位到最高位分别对数组A和k进行遍历, 求每一位上的和、进位, 一直到最后最高位相加并且处理完进位
* @param A 表示加数, 非负整数的数组A, A[0..length-1] 表示高位到低位
* @param K 表示被加数
* @return A[]和K对应整数相加后的和值(以列表形式存储)
*/
public List<Integer> addToArrayForm(int[] A, int K) {
if (A.length == 0) return null;
if (K < 0) K = -K;
int carry = 0;
List<Integer> list = new LinkedList<>();
for (int i = A.length-1; i >= 0 || K > 0 || carry > 0; i--, K/=10) {
int d = K > 0? K % 10: 0;
int n = i >= 0? A[i]: 0;
int sum = n + d + carry;
carry = 0;
if (sum > 9) {
sum -= 10;
carry ++;
}
list.add(0, sum);
}
return list;
}
改进
对参与加法的加数进行遍历的时候,考虑到的条件是一个或语句,包含了3个部分,能否简化一下,将它们合并到一起,以减少条件判断?
答案是可以的, 因为最终存储的实际上是 ( K+A[i] ) % 10 (K+A[i]个位数),是否进位也是看(K + A[i]) 的十位数是否有变化。不过,当前的十位数,也是下一次循环时的个位数。
for (int i = A.length-1; i >= 0 || K > 0 || carry > 0; i--, K/=10)
public List<Integer> addToArrayForm(int[] A, int K) {
if (A.length == 0 || K < 0) return null;
LinkedList<Integer> list = new LinkedList<>();
for (int i = A.length-1; i >=0 || K > 0; i--, K /= 10) {
if (i >= 0) {
K += A[i];
}
list.addFirst(K % 10);
}
return list;
}