leetcode 1734——解码异或后的排列
Posted thejohn2020
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 1734——解码异或后的排列相关的知识,希望对你有一定的参考价值。
今天leetcode每日一题是解码异或后的排列,我个人认为这道题非常巧妙,也能帮助我们更好地理解异或这个符号,同时也会发现它的神奇之处。
题目链接:https://leetcode-cn.com/problems/decode-xored-permutation/
这道题的意思是,有从1到n的数存到数组中(n是奇数),不过被重新排列了,用nums表示,但是我们不知道这个数组是什么,要求我们求出。题目给了我们一个数组encoded,满足encoded[i]=nums[i]^nums[i+1]。所以encoded数组的长度是nums-1。
这里要说的是异或是满足交换率的,即a^b=c 等价于 a ^c=b。所以要求出nums[i],就是nums[i]=nums[i-1] ^encoded[i-1]。因此只要我们得出nums[0]的值就可以毫不费力地推出nums中的所有值了。题目转换成求nums[0]就行了。
那么nums[0]怎么求,可以想到nums[0]=nums[0]^ nums[1]^nums[2] ^…… ^nums[n-1] ^ nums[1] ^nums[2] ^…… ^nums[n-1] ,这是因为异或的定义为相同为0,nums[0] ^nums[0]=0,0异或任何数都是它本身,那么我们可以把 nums[1] ^ nums[2] ^…… ^nums[n-1] 全部约掉,就只剩下了nums[0]。
题目就再次转换成求nums[0]^ nums[1]^nums[2] ^…… ^nums[n-1] 和 nums[1] ^nums[2] ^…… ^nums[n-1]了。
首先说前面的怎么求,题目已经说明,数字是从1到n,只是重新排列了,但是由于异或符合交换律。比如1 ^ 2 ^ 3=2 ^ 3^ 1,所以nums[0]^ nums[1]^nums[2] ^…… ^nums[n-1]其实就是1 ^2 ^3…… ^n,他们是等价的,无论nums如何排列,交换一下顺序永远都是这样的。
那么nums[1] ^nums[2] ^…… ^nums[n-1]怎么求,我们可以发现:
encoded[1]=nums[1] ^nums[2]
encoded[3]=nums[3] ^nums[4]
那么(nums[1]^ nums[2]) ^(nums[3] ^nums[4])=nums[1] ^nums[2] ^nums[3] ^nums[4]。 由于n是奇数,所以我们的encoded是一定不会少掉一个数字的。因此我们的 i 从1开始,i 每次加2,这样就可以得出nums[1] ^nums[2] ^…… ^nums[n-1]的结果。
代码如下:
class Solution {
public:
vector<int> decode(vector<int>& encoded) {
int n=encoded.size();
int a=0,b=0;
for(int i=1;i<=n+1;i++)
a^=i;
for(int i=1;i<n;i+=2)
b^=encoded[i];
vector<int> ret;
ret.push_back(a^b);
for(int i=0;i<n;i++)
ret.push_back(ret.back()^encoded[i]);
return ret;
}
};
代码中a是nums[0]^ nums[1]^nums[2] ^…… ^nums[n-1]的异或和。
b是nums[1] ^nums[2] ^…… ^nums[n-1]的异或和。
这样的话我们a^b就是nums[0]了。
至此,这道题就讲完啦,继续加油:)
以上是关于leetcode 1734——解码异或后的排列的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 1734 解码异或后的排列[数学] HERODING的LeetCode之路
我用java刷 leetcode 1734. 解码异或后的排列
LeetCode1734. 解码异或后的排列 / 剑指 Offer 36. 二叉搜索树与双向链表 / 剑指 Offer 37. 序列化二叉树