1. 程式人生 > 實用技巧 >格雷編碼-lc89

格雷編碼-lc89

題目連結:傳送門
題目大意:

對於給定的非負整數n,返回一個長度位$2^n$序列
要求:

  • 相鄰兩個數的位數僅有一位差距
  • 所有數字不相同
  • 第一個數字位0

解法一:(虛假的解法

class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> ans;
        ans.push_back(0);
      //遍歷位數
        for(int i = 0;i < n;i++){
            //取前一次長度遍歷
            for(int j = ans.size() - 1;j >= 0;j--){
                  //每次新增ans[j] ^ ( 1 << i),即令當前遍歷位數的bit為1
                ans.push_back(ans[j] ^ (1 << i));
            }
        }
        return ans;
    }
};
// 0000 0001 0011 0010 0110 0111 0101 0100 

上面的解法並不困難,且容易理解。

解法二

此解法我理解不深刻,有錯誤之處還請指正。

List<Integer> list = new ArrayList<>();
for(int i = 0;i < 1 << n;i++){
    ans.add(i ^ i >> 1);
}
return ans;

先證明相鄰兩數只差一位
$$
x \otimes (x >> 1) ^ ((x + 1) \otimes ((x + 1) >> 1))\
= [x \otimes (x + 1)] \otimes [(x >> 1) \otimes ((x + 1) >> 1)]\
$$
因此先計算$$x \otimes (x + 1) $$,不妨計算過程為下面的形式

同理另一半的值以為向右移動一位應該為下面的形式

很明顯可以知道最終的計算結果應該為

最終我們得到到了相鄰兩個數值差這一位。

而這些證明並不能代表我們的題解是正確的,還需要證明這$1 << n$個數完全不相等

考慮這樣的事:當n == 3時,我們已經有

0 , 1, 3, 2

那麼後買你4個數如和新增的呢,此時題解中的$i == 4$那麼$ i \otimes (i >> 1)$應該保留第一位的1,並且
$$
(x + 1) \otimes ((x + 1) >> 1)\
= x \otimes ( x >> 1) \otimes (x的最低一位0)\
$$
一旦$x$跨越$x^i - 1$的時候那麼 $x \otimes (x >> 1)$一定會保證最高一位是1,更細節一點的證明我想不出來了

算證明了3/4吧