# 给你一个整数数组 perm ,它是前 n 个正整数的排列,且 n 是个 奇数 。
#
# 它被加密成另一个长度为 n - 1 的整数数组 encoded ,满足 encoded[i] = perm[i] XOR perm[i + 1] 。比方说
# ,如果 perm = [1,3,2] ,那么 encoded = [2,1] 。
#
# 给你 encoded 数组,请你返回原始数组 perm 。题目保证答案存在且唯一。
#
#
#
# 示例 1:
#
# 输入:encoded = [3,1]
# 输出:[1,2,3]
# 解释:如果 perm = [1,2,3] ,那么 encoded = [1 XOR 2,2 XOR 3] = [3,1]
#
#
# 示例 2:
#
# 输入:encoded = [6,5,4,6]
# 输出:[2,4,1,5,3]
#
#
#
#
# 提示:
#
#
# 3 <= n < 105
# n 是奇数。
# encoded.length == n - 1
#
# Related Topics 位运算
# 👍 54 👎 0
本题有两个关键点,审题要细:
- perm是前 n 个正整数的排列
- n为奇数
只要能找出perm[0]
,就能结合encoded数组,递推出所有perm剩余元素。
由条件1可以得到perm[0] ^ ... ^ perm[n-1]
,只要求得perm[1] ^ ... ^ perm[n-1]
,二者异或即可得到perm[0]。
由条件2,结合encoded数组的特点:
[perm[0] ^ perm[1], perm[1] ^ perm[2], perm[2] ^ perm[3], perm[3] ^ perm[4],...]
只需将奇数下标的元素异或,即可得到perm[1] ^ ... ^ perm[n-1]
。
一开始计算perm[1] ^ ... ^ perm[n-1]
,用了笨方法,先求出p[0] ^ [p1], p[0] ^ p[2], ...,p[0] ^ p[n-1]
,再统统异或。由于n为奇数,所以p[0]共有偶数个,最后能消除掉:
class Solution:
def decode(self, encoded: List[int]) -> List[int]:
n = len(encoded) + 1
a2_to_an = encoded[0]
a1_to_ai = a2_to_an
for i in range(1, n-1):
a1_to_ai ^= encoded[i]
a2_to_an ^= a1_to_ai
a1_to_an = 0
for k in range(1, n+1):
a1_to_an ^= k
a1 = a2_to_an ^ a1_to_an
ret = [0] * n
ret[0] = a1
for i in range(1, n):
ret[i] = ret[i-1] ^ encoded[i-1]
return ret
改进后的代码,直接将奇数下标的元素异或,计算perm[1] ^ ... ^ perm[n-1]
:
# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
def decode(self, encoded: List[int]) -> List[int]:
n = len(encoded) + 1
a2_to_an = 0
for i in range(1, n-1, 2):
a2_to_an ^= encoded[i]
a1_to_an = 0
for k in range(1, n+1):
a1_to_an ^= k
a1 = a2_to_an ^ a1_to_an
ret = [0] * n
ret[0] = a1
for i in range(1, n):
ret[i] = ret[i-1] ^ encoded[i-1]
return ret
# leetcode submit region end(Prohibit modification and deletion)
官方题解用了reduce,代码更加简洁:
from functools import reduce
from operator import xor
class Solution:
def decode(self, encoded: List[int]) -> List[int]:
n = len(encoded) + 1
a1_to_an = reduce(xor, range(1, n+1))
a2_to_an = reduce(xor, encoded[1 : n-1 : 2])
a1 = a2_to_an ^ a1_to_an
ret = [0] * n
ret[0] = a1
for i in range(1, n):
ret[i] = ret[i-1] ^ encoded[i-1]
return ret
# leetcode submit region end(Prohibit modification and deletion)
解答成功:
执行耗时:184 ms,击败了89.02% 的Python3用户
内存消耗:29.6 MB,击败了82.93% 的Python3用户
附:异或运算定律
- 异或本身值为0:
x ^ x = 0
- 异或0值为本身:
x ^ 0 = x
- 可交换:
x ^ y = y ^ x
- 可结合:
x ^ (y ^ z) = (x ^ y) ^ z
附:reduce方法
reduce方法的定义为:
reduce(function, iterable[, initializer])
# function -- 函数,有两个参数
# iterable -- 可迭代对象
# initializer -- 可选,初始参数