LeetCode刷题之路-每日一题-1734. 解码异或后的排列

前言

其实吧,今天这题我是放弃的。这位运算其中的规律,根本就不懂。于是看了一下题解。

题目描述


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


解题思路

  1. 异或的秘密
  2. 题目中的重要信息和重要提示
    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;
    }

总结

异或特点

  1. A XOR B = B XOR A
  2. A XOR B XOR B = A
  3. 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值