前言
其实吧,今天这题我是放弃的。这位运算其中的规律,根本就不懂。于是看了一下题解。
题目描述
给你一个整数数组 perm ,它是前 n 个正整数的排列,且 n 是个 奇数 。
它被加密成另一个长度为 n - 1 的整数数组 encoded ,满足 encoded[i] = perm[i] XOR perm[i + 1] 。比方说,如果 perm = [1,3,2] ,那么 encoded = [2,1] 。
给你 encoded 数组,请你返回原始数组 perm 。题目保证答案存在且唯一。
提示:
3 <= n < 105
n 是奇数。
encoded.length == n - 1
解题思路
- 异或的秘密
- 题目中的重要信息和重要提示
2.1 一个整数数组 perm ,它是前 n 个正整数的(随机/任意次序)排列 - 随机是我加上去的,不然看题解都整不明白。。。坑!
2.2 n是奇数 - 意味着在求解perm[0]不需要考虑偶数的情况
写完再逛下评论区,果然还有大神:
前n项的XOR可以简化
当n=3时, XOR(3) = 1 XOR 2 XOR 3 = 0
当n=5时, XOR(5) = XOR(3) XOR 4 XOR 5 = 1
当n=7时, XOR(7) = XOR(5) XOR 6 XOR 7 = 0
当n=9时, XOR(9) = XOR(7) XOR 8 XOR 9 = 1
…
但是大佬不止看到这个还有偶数的,只不过题目不存在偶数,n为奇数
当n=4时, XOR(4) = XOR(3) XOR 4 = 4 = n
当n=6时, XOR(6) = XOR(5) XOR 6 = 7 = n + 1
当n=8时, XOR(8) = XOR(7) XOR 8 = 8 = n
当n=10时, XOR(10) = XOR(9) XOR 10 = 11 = n + 1
于是写出如下优化代码
int n = encoded.size();
int xorN;
switch ((n + 1) % 4) {
case 1: {
xorN = 1;
break;
} case 2: {
xorN = n + 2;
break;
} case 3: {
xorN = 0;
break;
} default: {
xorN = n + 1;
break;
}
}
具体的我都写到代码里了,上代码
代码
public int[] decode(int[] encoded) {
// 异或
// A XOR B = C
// 则有如下关系
// 0 XOR 0 = 0
// 0 XOR 1 = 1
// 1 XOR 0 = 1
// 1 XOR 1 = 0
// 而题目要求我们是从异或的结果反推原始值,而我们发现
// B XOR C
// 0 XOR 0 = 0
// 1 XOR 1 = 0
// 0 XOR 1 = 1
// 1 XOR 0 = 1
// 刚好 B XOR C = A
// 又因为 encoded[i] = perm[i] XOR perm[i + 1]
// 所以有 perm[i + 1] = perm[i] XOR encoded[i];
// 因此,只要我们能找出 perm[0]就能通过该递推公式找出原数组中的每一个元素
// 于是问题又变成了求第一个原始元素
// 如果A OR B 记作 AB,那么
// 而 A XOR B XOR B = A
// 所以可通过 perm[0] = perm[0] XOR (perm[1] XOR perm[2] XOR perm[n-1]) XOR (perm[1] XOR perm[2] XOR perm[n-1])
// = (perm[0] XOR perm[1] XOR perm[2] XOR perm[n-1]) XOR (perm[1] XOR perm[2] XOR perm[n-1])
// 因为 perm是前n个正整数的(随机)排列,
// 所以有
// (perm[0] XOR perm[1] XOR perm[2] XOR perm[n-1])
// = 1 XOR 2 XOR ... XOR n
// 而 encodeded = [AB,BC,CD,...]
// 所以
// (perm[1] XOR perm[2] XOR perm[n-1])
// = encodeded[1] XOR encodeded[3] XOR encodeded[3] XOR ... XOR encodeded[n-1]
// 所以 perm[0] = (1 XOR 2 XOR ... XOR n)
// XOR (encodeded[1] XOR encodeded[3] XOR encodeded[3] XOR ... XOR encodeded[n-1])
int allXOR = 0;
// 这里需要注意下,是前n项的随机排列,而encoded数组长度会比原数组少一个长度
for (int i=1;i<=encoded.length + 1;i++) {
allXOR ^= i;
}
for (int i=1; i<encoded.length;i+=2) {
allXOR ^= encoded[i];
}
// 到这里 allXOR 就是perm[0]了
int[] perm = new int[encoded.length + 1];
perm[0] = allXOR;
for (int i=1;i<=encoded.length;i++) {
perm[i] = encoded[i-1] ^ perm[i - 1];
}
return perm;
}
总结
异或特点
- A XOR B = B XOR A
- A XOR B XOR B = A
- A XOR B = C
则有 A = B XOR C
B = A XOR C
最后,这几天存的粮还有待整理,ThreadLocal及它的ThreadLocalMap,今天:多线程的数据一致性与性能之间的博弈-CPU层面的解决方案与java的实现。
先Mark一下大佬的博客,晚安:
https://www.cnblogs.com/hello-shf/p/12091591.html