# 题目描述
负二进制数相加
给出基数为 -2
的两个数 arr1
和 arr2
,返回两数相加的结果。
数字以 数组形式 给出:数组由若干 0 和 1 组成,按最高有效位到最低有效位的顺序排列。例如,arr = [1,1,0,1]
表示数字 (-2)^3 + (-2)^2 + (-2)^0 = -3
。数组形式 中的数字 arr
也同样不含前导零:即 arr == [0]
或 arr[0] == 1
,不存在arr = [0, 0 ,1]
这种形式
返回相同表示形式的 arr1
和 arr2
相加的结果。两数的表示形式为:不含前导零、由若干 0
和 1
组成的数组。
# 测试用例
示例1:
- 输入:
arr1 = [1,1,1,1,1], arr2 = [1,0,1]
- 输出:
[1,0,0,0,0]
- 解释:
arr1
表示11
,arr2
表示5
,输出表示16
。
示例2:
- 输入:
arr1 = [0], arr2 = [0]
- 输出:
[0]
示例3:
- 输入:
arr1 = [0], arr2 = [1]
- 输出:
[1]
# 分析
普通的二进制相加
从低位到高位进行加法运算,在运算的过程中维护一个进位变量carry
,carry
默认为0
设当前位置该放入的值为cur
, 则x = arr[i] + arr[j] + carry
—— 例如 arr[i] = 0
, arr[j] = 1
, carry = 0
, 则x = 1
x = 0
或1
时,cur = x
,同时不进位,carry = 0
;x = 2
或3
时,cur = x - 2
, 要进位,carry = 1
;
比如 arr[i] = 1, arr[j] = 1, carry = 1, 则该位置该放入的值为 3 - 2 = 1,同时进位carry = 1,再进行下一个位置的加法运算
负二进制数相加
与普通二进制计算方式一样,只是处理时需要做一下改变
从低位到高位进行加法运算,在运算的过程中维护一个变量 carry
,carry
默认为0
设当前位置该放入的值为cur
, 则x = arr[i] + arr[j] + carry
—— 例如 arr[i] = 0, arr[j] == 1, carry = 0
, 则x = 1
x = 0
或1
时,cur = x
,同时不进位,carry = 0
;x = 2
时,cur = x - 2
,同时进位,注意此时的进位就变成了-1
,即carry = -1
,因为下一位的值与该位置的值的符号是相反的,所以要进位负数x = -1
时,cur = 1
,同时进位,注意进位应该是1
, 即carry = 1
,因为让该位置取1
,下一个位置也取1
,两者的和正好表示该位置进制对应是-1
的情况(如下图公式)x = 3
时,与x=2
的操作时一样的。
$$ -(-2)^i = (-2)^i+1 + (-2)^2 $$
👇 注意:
最坏情况下,当计算完二者最高位的x
后,得到x = 3
,此时会产生-1
的进位, 在之后又会产生 1
的进位,因此,答案的长度最多为 arr1
和 arr2
最大长度 + 2;
我们需要处理到进位为0
的地方,也就是虽然遍历完两个数组,但进位不为0
时仍要继续处理
# 代码实现
/**
* @param {number[]} arr1
* @param {number[]} arr2
* @return {number[]}
*/
var addNegabinary = function (arr1, arr2) {
let i = arr1.length - 1;
let j = arr2.length - 1;
let carry = 0;
let ans = [];
// 两个数组长度不一样,所以要用或来判断结束
// 同时要判断carry,如果遍历完最大长度后不为0,就要往前继续进位计算,直到carry = 0
while (i >= 0 || j >= 0 || carry !== 0) {
let x = carry;
if (i >= 0) {
x += arr1[i];
}
if (j >= 0) {
x += arr2[j];
}
// 开始判断
if (x >= 2) {
// 相加等于2或3
ans.unshift(x - 2);
carry = -1;
} else if (x >= 0) {
// 相加为0或1
ans.unshift(x);
carry = 0;
} else {
// 相加等于 -1
ans.unshift(1);
carry = 1;
}
j--;
i--;
}
while (ans.length > 1 && ans[0] == 0) {
ans.splice(0, 1);
}
return ans;
// 去除前导零
};
var __readline = require("readline-sync");
__readline.setDefaultOptions({ prompt: "" });
var readline = __readline.prompt;
let arr1 = [];
console.log("请输入arr1: ");
let line1 = readline().split(" ").map(Number);
for (let i = 0; i < line1.length; i++) {
arr1.push(line1[i]);
}
// console.log(arr1);
let arr2 = [];
console.log("请输入arr2: ");
let line2 = readline().split(" ").map(Number);
for (let i of line2) {
arr2.push(i);
}
// console.log(arr2);
let res = addNegabinary(arr1, arr2);
console.log("结果为: ", res);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79