leetcode[1734]解码异或后的排列 Python3实现(异或操作,附异或运算定律)

# 给你一个整数数组 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

本题有两个关键点,审题要细:

  1. perm是前 n 个正整数的排列
  2. 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用户

附:异或运算定律

  1. 异或本身值为0:x ^ x = 0
  2. 异或0值为本身:x ^ 0 = x
  3. 可交换:x ^ y = y ^ x
  4. 可结合:x ^ (y ^ z) = (x ^ y) ^ z

附:reduce方法

reduce方法的定义为:

reduce(function, iterable[, initializer])

# function -- 函数,有两个参数
# iterable -- 可迭代对象
# initializer -- 可选,初始参数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值