返回介绍

solution / 1200-1299 / 1238.Circular Permutation in Binary Representation / README_EN

发布于 2024-06-17 01:03:21 字数 6791 浏览 0 评论 0 收藏 0

1238. Circular Permutation in Binary Representation

中文文档

Description

Given 2 integers n and start. Your task is return any permutation p of (0,1,2.....,2^n -1)such that :

  • p[0] = start
  • p[i] and p[i+1] differ by only one bit in their binary representation.
  • p[0] and p[2^n -1] must also differ by only one bit in their binary representation.

 

Example 1:


Input: n = 2, start = 3

Output: [3,2,0,1]

Explanation: The binary representation of the permutation is (11,10,00,01). 

All the adjacent element differ by one bit. Another valid permutation is [3,1,0,2]

Example 2:


Input: n = 3, start = 2

Output: [2,6,7,5,4,0,1,3]

Explanation: The binary representation of the permutation is (010,110,111,101,100,000,001,011).

 

Constraints:

  • 1 <= n <= 16
  • 0 <= start < 2 ^ n

Solutions

Solution 1: Binary Code to Gray Code

We observe the arrangement in the problem, and find that in its binary representation, only one bit is different between any two (including the first and last) adjacent numbers. This kind of coding method is Gray code, which is a coding method we will encounter in engineering.

The rule for converting binary code to binary Gray code is to keep the highest bit of the binary code as the highest bit of the Gray code, and the second highest bit of the Gray code is the XOR of the highest bit and the second highest bit of the binary code. The rest of the Gray code is similar to the second highest bit.

Assume a binary number is represented as $B_{n-1}B_{n-2}…B_2B_1B_0$, its Gray code representation is $G_{n-1}G_{n-2}…G_2G_1G_0$. The highest bit is kept, so $G_{n-1} = B_{n-1}$; and the other bits $G_i = B_{i+1} \oplus B_{i}$, where $i=0,1,2..,n-2$.

Therefore, for an integer $x$, we can use the function $gray(x)$ to get its Gray code:

int gray(x) {
  return x ^ (x >> 1);
}

We can directly convert the integers $[0,..2^n - 1]$ into the corresponding Gray code array, then find the position of $start$ in the Gray code array, cut the Gray code array from this position, and then append the cut part to the front of the Gray code array to get the arrangement required by the problem.

The time complexity is $O(2^n)$, and the space complexity is $O(2^n)$. Where $n$ is the integer given in the problem.

class Solution:
  def circularPermutation(self, n: int, start: int) -> List[int]:
    g = [i ^ (i >> 1) for i in range(1 << n)]
    j = g.index(start)
    return g[j:] + g[:j]
class Solution {
  public List<Integer> circularPermutation(int n, int start) {
    int[] g = new int[1 << n];
    int j = 0;
    for (int i = 0; i < 1 << n; ++i) {
      g[i] = i ^ (i >> 1);
      if (g[i] == start) {
        j = i;
      }
    }
    List<Integer> ans = new ArrayList<>();
    for (int i = j; i < j + (1 << n); ++i) {
      ans.add(g[i % (1 << n)]);
    }
    return ans;
  }
}
class Solution {
public:
  vector<int> circularPermutation(int n, int start) {
    int g[1 << n];
    int j = 0;
    for (int i = 0; i < 1 << n; ++i) {
      g[i] = i ^ (i >> 1);
      if (g[i] == start) {
        j = i;
      }
    }
    vector<int> ans;
    for (int i = j; i < j + (1 << n); ++i) {
      ans.push_back(g[i % (1 << n)]);
    }
    return ans;
  }
};
func circularPermutation(n int, start int) []int {
  g := make([]int, 1<<n)
  j := 0
  for i := range g {
    g[i] = i ^ (i >> 1)
    if g[i] == start {
      j = i
    }
  }
  return append(g[j:], g[:j]...)
}
function circularPermutation(n: number, start: number): number[] {
  const ans: number[] = [];
  for (let i = 0; i < 1 << n; ++i) {
    ans.push(i ^ (i >> 1) ^ start);
  }
  return ans;
}

Solution 2: Conversion Optimization

Since $gray(0) = 0$, then $gray(0) \oplus start = start$, and $gray(i)$ is only one binary bit different from $gray(i-1)$, so $gray(i) \oplus start$ is also only one binary bit different from $gray(i-1) \oplus start$.

Therefore, we can also directly convert the integers $[0,..2^n - 1]$ into the corresponding $gray(i) \oplus start$ to get the Gray code arrangement with $start$ as the first term.

The time complexity is $O(2^n)$, where $n$ is the integer given in the problem. Ignoring the space consumption of the answer, the space complexity is $O(1)$.

class Solution:
  def circularPermutation(self, n: int, start: int) -> List[int]:
    return [i ^ (i >> 1) ^ start for i in range(1 << n)]
class Solution {
  public List<Integer> circularPermutation(int n, int start) {
    List<Integer> ans = new ArrayList<>();
    for (int i = 0; i < 1 << n; ++i) {
      ans.add(i ^ (i >> 1) ^ start);
    }
    return ans;
  }
}
class Solution {
public:
  vector<int> circularPermutation(int n, int start) {
    vector<int> ans(1 << n);
    for (int i = 0; i < 1 << n; ++i) {
      ans[i] = i ^ (i >> 1) ^ start;
    }
    return ans;
  }
};
func circularPermutation(n int, start int) (ans []int) {
  for i := 0; i < 1<<n; i++ {
    ans = append(ans, i^(i>>1)^start)
  }
  return
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文