这是我参与更文挑战的第9天,活动详情查看: 更文挑战
解码异或后的数组(题号1720)
题目
未知 整数数组 arr
由 n
个非负整数组成。
经编码后变为长度为 n - 1
的另一个整数数组 encoded
,其中 encoded[i] = arr[i] XOR arr[i + 1]
。例如,arr = [1,0,2,1]
经编码后得到 encoded = [1,2,3]
。
给你编码后的数组 encoded
和原数组 arr
的第一个元素 first(arr[0])
。
请解码返回原数组 arr
。可以证明答案存在并且是唯一的。
示例 1:
输入:encoded = [1,2,3], first = 1
输出:[1,0,2,1]
解释:若 arr = [1,0,2,1] ,那么 first = 1 且 encoded = [1 XOR 0, 0 XOR 2, 2 XOR 1] = [1,2,3]
示例 2:
输入:encoded = [6,2,7,3], first = 4
输出:[4,2,0,7,4]
提示:
2 <= n <= 104
encoded.length == n - 1
0 <= encoded[i] <= 105
0 <= first <= 105
链接
解释
这题啊,这题是小学二年级学过的知识。
异或这个方法其实比较狗,具体就不介绍啦,篇幅较长,有兴趣的可以自行查阅相关资料。
这里只要当前一种计算方法,或者说一个符号即可,类似于加减乘除。
异或方法有如下特点:
- 异或运算满足交换律和结合律
- 任意整数和自身做异或运算的结果都等于 0,即
x⊕x=0
; - 任意整数和 0 做异或运算的结果都等于其自身,即
x⊕0=0⊕x=x
。
这里的⊕
就是题目上的XOR
——异或运算。
首先看看交换律和结合律,这一点在小学就学过啦,和乘法类似,在等式两边可以随意添加元素,那么此时从正常的异或运算式开始推导,可以得到这样的过程👇:
encoded[i−1] = arr[i−1] ⊕ arr[i]
encoded[i−1] ⊕ arr[i−1] = arr[i−1] ⊕ arr[i] ⊕ arr[i−1]
arr[i−1] ⊕ encoded[i−1] = arr[i−1] ⊕ arr[i−1] ⊕ arr[i]
arr[i−1] ⊕ encoded[i−1] = 0 ⊕ arr[i]
arr[i−1] ⊕ encoded[i−1] = arr[i]
整个推导过程就是利用👆说到的三个特性,从而得出反向推到出arr[i]
的公式,拿到这个公式后就可以反向得出原数组啦~
自己的答案
无
更好的方法(官方解法)
官方解法就比较简单了👇:
var decode = function(encoded, first) {
const n = encoded.length + 1;
const arr = new Array(n).fill(0);
arr[0] = first;
for (let i = 1; i < n; i++) {
arr[i] = arr[i - 1] ^ encoded[i - 1];
}
return arr;
};
对吧,就是这么简单,没有多余的操作。
但是性能比较一般,👇介绍笔者觉得比较好的方法。
更好都方法(节省空间)
官方解法其实新建了一个对象来存储反向转化后的数组,这里直接修改原数组,也就是encoded
数组,修改完成后直接返回即可。
var decode = function(encoded, first) {
encoded.unshift(first)
for (let i = 1; i < encoded.length; i++) {
encoded[i] = encoded[i - 1] ^ encoded[i]
}
return encoded
};
更好的方法(节省时间)
这种方法就和原方法差不多了,稍微优化了一下。
var decode = function(encoded, first) {
let cur = first
let result = [first]
for (let e of encoded) {
cur = cur ^ e
result.push(cur)
}
return result
};
这两种方法笔者感觉都比官方答案好些,有兴趣的可以点击这里查看原答案。
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇
有兴趣的也可以看看我的个人主页👇