Adding Two Negabinary Numbers 负二进制数相加
问题描述:
给出基数为 -2 的两个数 arr1 和 arr2,返回两数相加的结果。
数字以 数组形式 给出:数组由若干 0 和 1 组成,按最高有效位到最低有效位的顺序排列。例如,arr = [1,1,0,1] 表示数字 ( − 2 ) 3 + ( − 2 ) 2 + ( − 2 ) 0 = − 3 (-2)^3 + (-2)^2 + (-2)^0 = -3 (−2)3+(−2)2+(−2)0=−3。数组形式 中的数字 arr 也同样不含前导零:即 arr = [0] 或 arr[0] = 1。
返回相同表示形式的 arr1 和 arr2 相加的结果。两数的表示形式为:不含前导零、由若干 0 和 1 组成的数组。
arr1.length, arr2.length范围[1,1000]
arr1[i],arr2[i]只能是0,1
arr1,arr2不存在前导零
分析
如果数据范围小的情况下,还可以思考转换为十进制计算后,再转换为负二进制,但是以目前问题的数据规模,很明显是个大数,只能通过模拟的方式,来处理。
首先要知道负二进制和负数的二进制,这2个不是一回事。
负数的二进制表示,就是 负数的绝对值的真值部分[取反]再+1,也就是负数的补码.
而负二进制,就不一样的,它不同与二进制,每一位都是2,在这里每一位都是(-2),
对于2进制来说,两数的加法,就是a1[i]+a2[i]+carry,carry就是[进位],从低到高二进制每一位[位权]是 1,2,4,8。当第i位加和后>=2,就可以进位,carry=1。
二进制中的每一位范围就是[0,1],不考虑进位的情况下加和后范围[0,2],再算carry,范围就是[0,3].
但是-2进制,就不一样,从低到高的每一位[位权]是,1,-2,4,-8.负2进制的位权是正负交替的,
所以当第i位发生进位,此时需要在i+1位上用-1表示,carry=-1。
也就是说,记累加和 x= a1[i]+a2[i]+carry,x范围[0,1],就不存在进位,carry=0;x= 2时,说明发生了进位,carry=-1,同时当前位保留x-2;x=-1时,说明当前有一个进位需要处理,具体处理方式,当前位为i时,
−
1
∗
(
−
2
)
i
=
(
−
2
)
i
+
1
+
(
−
2
)
i
-1*(-2)^i = (-2)^{i+1}+(-2)^i
−1∗(−2)i=(−2)i+1+(−2)i,可以发现第i+1位需要加1,所以carry=1,同时当前位置1。
此时 carry的最大值可以到1,所以 x的最大值就可以到3,这里和x=2时一样,处理carry和保留当前位的值。
相加处理,然后要注意的就是数组尾部为低位,所以需要逆序处理,最后的结果还需要删掉前导零,再reverse。
代码
class Solution {
public int[] addNegabinary(int[] arr1, int[] arr2) {
int i = arr1.length - 1, j = arr2.length - 1;
int carry = 0;
List<Integer> ans = new ArrayList<Integer>();
while (i >= 0 || j >= 0 || carry != 0) {
int x = carry;
if (i >= 0) {
x += arr1[i];
}
if (j >= 0) {
x += arr2[j];
}
if (x >= 2) {
ans.add(x - 2);
carry = -1;
} else if (x >= 0) {
ans.add(x);
carry = 0;
} else {
ans.add(1);
carry = 1;
}
--i;
--j;
}
while (ans.size() > 1 && ans.get(ans.size() - 1) == 0) {
ans.remove(ans.size() - 1);
}
int[] arr = new int[ans.size()];
for (i = 0, j = ans.size() - 1; j >= 0; i++, j--) {
arr[i] = ans.get(j);
}
return arr;
}
}
时间复杂度 O(N+M) 空间复杂度: O(1)
Tag
Array
Math