Skip to content

Latest commit

 

History

History

1734

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

There is an integer array perm that is a permutation of the first n positive integers, where n is always odd.

It was encoded into another integer array encoded of length n - 1, such that encoded[i] = perm[i] XOR perm[i + 1]. For example, if perm = [1,3,2], then encoded = [2,1].

Given the encoded array, return the original array perm. It is guaranteed that the answer exists and is unique.

 

Example 1:

Input: encoded = [3,1]
Output: [1,2,3]
Explanation: If perm = [1,2,3], then encoded = [1 XOR 2,2 XOR 3] = [3,1]

Example 2:

Input: encoded = [6,5,4,6]
Output: [2,4,1,5,3]

 

Constraints:

  • 3 <= n < 105
  • n is odd.
  • encoded.length == n - 1

Related Topics:
Bit Manipulation

Solution 1.

A common trick of solve bit manipulation problem on an array of numbers is to consider them bit by bit.

Consider the i-th bit of all the numbers. It only has two options, 0 or 1. If we use 0 there, we can use the encoded array to deduce the i-th bits of all the other numbers. We can count the number of 1s and compare the count with the count of 1s at the i-th bit of integers from 1 to N.

If the counts match, we choose 0. Otherwise we choose 1.

Since N is at most 1e5, so just need to compare 0-th to floor(log2(1e5)) = 16-th bits.

Is it possible that choosing 0 or 1 results in the same count? No, because choosing 0 or 1 will yield two exactly opposite sequence. Since n is odd, these two sequence won't have the same number of 1s.

// OJ: https://leetcode.com/problems/decode-xored-permutation/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(1)
class Solution {
public:
    vector<int> decode(vector<int>& A) {
        int N = A.size() + 1;
        vector<int> ans(N);
        for (int i = 0; i <= 16; ++i) {
            int target = 0, bit = 0, cnt = 0;
            for (int j = 1; j <= N; ++j) target += j >> i & 1;
            for (int n : A) {
                bit ^= n >> i & 1;
                cnt += bit;
            }
            ans[0] |= (cnt != target) << i;
            for (int j = 1; j < N; ++j) {
                int x = A[j - 1] >> i & 1, prev = ans[j - 1] >> i & 1, b = x ^ prev;
                ans[j] |= b << i;
            }
        }
        return ans;
    }
};

Solution 2.

If we can find the correct first number, we can deduce all other numbers in O(N) time.

To find the first number, we can use the fact that n is odd. So:

a2 ^ a3 = A[1]
a4 ^ a5 = A[3]
...

So a2 ^ a3 ^ a4 ^ ... ^ an = A[1] ^ A[3] ^ ...

Since a1 ^ a2 ^ a3 ^ ... ^ an = 1 ^ 2 ^ 3 ^ ... ^ n, a1 = 1 ^ 2 ^ 3 ^ ... ^ n ^ A[1] ^ A[3] ^ ....

// OJ: https://leetcode.com/problems/decode-xored-permutation/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(1)
// Ref: https://leetcode.com/problems/decode-xored-permutation/discuss/1031107/JavaC%2B%2BPython-Straight-Forward-Solution
class Solution {
public:
    vector<int> decode(vector<int>& A) {
        int first = 0;
        for (int i = 1; i < A.size(); i += 2) first ^= A[i];
        for (int i = 1; i <= A.size() + 1; ++i) first ^= i;
        vector<int> ans = {first};
        for (int n : A) ans.push_back(n ^ ans.back());
        return ans;
    }
};

Actually since n is odd, we can get the 1 ^ 2 ^ 3 ^ ... ^ n in O(1) time.

Since 2 ^ 3 = 1, 4 ^ 5 = 1, 6 ^ 7 = 1 ..., so XOR(1) = 1, XOR(3) = 0, XOR(5) = 1, XOR(7) = 0 ... where XOR(n) = 1 ^ 2 ^ ... ^ n.

So XOR(n) = 1 - n / 2 % 2.

// OJ: https://leetcode.com/problems/decode-xored-permutation/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(1)
// Ref: https://leetcode.com/problems/decode-xored-permutation/discuss/1031107/JavaC%2B%2BPython-Straight-Forward-Solution
class Solution {
public:
    vector<int> decode(vector<int>& A) {
        int N = A.size() + 1, first = 1 - N / 2 % 2;
        for (int i = 1; i < A.size(); i += 2) first ^= A[i];
        vector<int> ans = {first};
        for (int n : A) ans.push_back(n ^ ans.back());
        return ans;
    }
};