給定非負整數 n,生成 n 位元格雷碼序列。格雷碼特性:相鄰兩碼僅差 1 位,且必以 0 開頭。
n = 2: [0, 1, 3, 2] 二進位: 00, 01, 11, 10 ← 每步僅翻轉 1 位 另一合法解: [0, 2, 3, 1] (00, 10, 11, 01)
n 位格雷碼可由 n-1 位構造:
n-1 位序列0,後半加前綴 1(即加 1 << (n-1))import java.util.ArrayList;
public class GrayCode {
public ArrayList<Integer> grayCode(int n) {
ArrayList<Integer> res = new ArrayList<>();
res.add(0); // n=0 時序列
for (int i = 1; i <= n; ++i) {
int prefix = 1 << (i - 1); // 最高位掩碼
int size = res.size();
// 逆序遍歷原序列,加上前綴
for (int j = size - 1; j >= 0; --j) {
res.add(res.get(j) + prefix);
}
}
return res;
}
}
i=1: [0] → [0, 1] (前綴 1) i=2: [0, 1] → [0, 1, 3, 2] (前綴 2) i=3: [0, 1, 3, 2] → [0, 1, 3, 2, 6, 7, 5, 4] (前綴 4)
第 i 個格雷碼:G(i) = i ^ (i >> 1)
i >> 1:右移一位^:異或運算public class GrayCode2 {
public ArrayList<Integer> grayCode(int n) {
ArrayList<Integer> res = new ArrayList<>();
int total = 1 << n; // 2^n
for (int i = 0; i < total; ++i) {
res.add((i >> 1) ^ i);
}
return res;
}
}
| i | 二進位 | i>>1 | 異或結果 | 十進位 |
|---|---|---|---|---|
| 0 | 000 | 000 | 000 | 0 |
| 1 | 001 | 000 | 001 | 1 |
| 2 | 010 | 001 | 011 | 3 |
| 3 | 011 | 001 | 010 | 2 |
| 4 | 100 | 010 | 110 | 6 |
| 5 | 101 | 010 | 111 | 7 |
| 6 | 110 | 011 | 101 | 5 |
| 7 | 111 | 011 | 100 | 4 |
| 維度 | 遞歸鏡像 | 位運算公式 |
|---|---|---|
| 時間複雜度 | O(2^n) | O(2^n) |
| 空間複雜度 | O(2^n) | O(2^n) |
| 理解難度 | 直觀易懂 | 需知公式 |
| 程式碼長度 | 較長 | 極短 |
| 擴展性 | 易於生成路徑 | 僅生成序列 |