2021-01-26 leetcode 1734. 解码异或后的
2021-01-26 本文已影响0人
fanchuang
1734. 解码异或后的排列.png
见注释!
# 题目 1734 https://leetcode-cn.com/problems/decode-xored-permutation/
""" 异或运算的基础知识:
概念理解:
1. 异或,英文为exclusive OR,缩写成xor, python3: a^b, 3^5
2. 异或, 满足加法结合律和交换律
3. 异或, 也叫半加运算, 相当于不带进位的二进制加法
4. 不是这个就是那个。“我明天要么去北京,要么去上海”
5. 异或的可逆运算, 本质上还是一个结合律
49 ^ 213 ^ 213 -> 49 ^ (213 ^ 213) -> 49 ^ 0 -> 49
定律:
1. 如果有 a^b=c, 必有 a^c=b, 也必然有 b^c=a
2. if a !=b: a^b=1, if a=b: a^b = 0
3. a ^ a = 0 a ^ 0 = a # 任何数与 0 异或,都等于它自身。
4. a^b^c = b^c^a = c^b^a, 这里的交换律是解题的关键。
5. 一句话总结:
1. 7^8^9 = 8^7^9 = 9^7^8 = 6,
2. 其中, 7^8 = 15, 15^9=6
3. 这个 15 就是中间的一个 中转站。
"""
""" 题目分析
考察的是数学上的东西啊!!!!
这个解释真的是非常好啊!!!!
https://leetcode-cn.com/problems/decode-xored-permutation/solution/ling-ji-yi-dong-de-jie-fa-by-motmlsc-5zkm/
“”
1. 只需要求出 原始数组的第一个数,那么其他的就迎刃而解了。
a1 = (n以内所有数的 累积异或值) ^ (a2^a3...a^)
进而,转化成了,需要求出 (a2^a3...a^)
2. 已经知道:
1, a1^a2^a3...^a(n) = range(1, n+1) 之间所有数的累计异或。
2, a1^a2 ^ a2^a3 ^ a3^a4 ...^ a(n-1)^a(n) = encoded 里面所有数的累计异或 = a1^an (这最后一个等号是我自己的想法)
3. 但是如果仔细观察上面的等式就会发现,如果我们跳着选 a2^a3, a4^a5,...,a(n-1)^a(n)
最终的结果刚好就是需要求的 (a2^a3...a^)
而且,题目说 n是奇数,则encoded一定是一个长度为偶数的数组。
"""
def decode(encoded):
n = len(encoded) + 1
# 1. 这里表示的 1, 2, 3, ... ,n 之间所有数异或的和。而且,有 a ^ 0 = a,所以可以初始化为 0
xor_all = 0
for i in range(1, n+1):
xor_all ^= i
# print("xor_all", xor_all) # 1
# 2. 初始化为 0
a2_an = 0
# 由于需要跳着选取,最好是使用下标。
for j in range(1, len(encoded)+1, 2):
a2_an ^= encoded[j]
# print(a2_an)
# 3. 求出 a1
a1 = xor_all ^ a2_an
# print(a1)
# 4. 然后求出剩下所有的值。
ret = [a1]
temp = a1
for h in encoded:
ret.append(h^temp)
temp = h^temp
# print(ret)
return ret
encoded = [6,5,4,6]
decode(encoded)