2021-01-26 leetcode 1734. 解码异或后的排列

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)

你可能感兴趣的:(2021-01-26 leetcode 1734. 解码异或后的排列)