1734解码异或后的排列
问题描述:
给你一个整数数组 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]
思路:
- 写过1720题的小伙伴应该懂这个问题应该怎么写,很明显,如果没有几个约束条件的话,我们可以得出n种不同的结果,但是要求perm是一个前n个正整数的排列,那么结果就只有一个了,那到底是哪一种排列呢?
- 1720题地址
根据上次的结论,如果a异或b = c,那么abc三个值任意两个的异或都等于第三个值。有了这个结论,我们就可以得知,如果确定了perm中的一个值,那么整个perm数组就可以确定下来。但是那一个值应该怎么确定呢?
因为perm是一个从1到n的一个排列,所以perm中所有元素的异或我们是可以直接算出来的。也就是1 ^ 2 ^ 3 . . . ^ n,而如果我们能求出perm[ 1 ]^…perm[ n ]的话,我们就可以求出perm[ 0 ]的值,这样我们就可以确定perm中的第一个数字,进而可以求出perm中所有的数字。
又因为 encoded[i] = perm[i] XOR perm[i + 1]
这里的encoded[ i ]等于perm中两个数的异或,那么同样的,encoded[i+2] = perm[i+2] XOR perm[i+3]
。这样的话,我们就可以通过encoded来求出perm[ 1 ]异或到perm[ n ]。也就解决了问题。
Java代码:
/**
* @Description: 力扣1734题题解
* @return: 返回结果
* @Author: Mr.Gao
* @Date: 2021/5/11
*/
public int[] decode2(int[] encoded){
int n = encoded.length+1;
int total = 0;
for(int i=1;i<=n;i++){
total^=i;
}
int odd = 0;
for(int i=1;i<n-1;i+=2){
odd^=encoded[i];
}
int[] perm = new int[n];
perm[0] = total^odd;
for (int i = 0; i < n-1; i++) {
perm[i+1] = perm[i]^encoded[i];
}
return perm;
}
- 这个是官方题解给的思路,而我的思路呢…就是暴力遍历从1到n,找到最合适的0号位置的值,不出意外,果然爆掉了。
错误的Java代码:
/**
* @Description: 力扣1734题题解
* @return: 返回结果
* @Author: Mr.Gao
* @Date: 2021/5/11
*/
public int[] decode(int[] encoded) {
int n = encoded.length;
int[] a = new int[n+1];
for(int i=1;i<=n;i++){
a[0] = i;
int j=0;
for (j = 0; j < n; j++) {
a[j+1] = a[j]^encoded[j];
if(a[j+1]>n+1||a[j+1]<0){
break;
}
}
if(j==n){
return a;
}
}
return null;
}