格雷编码-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吧

原文地址:https://www.cnblogs.com/yvzhu/p/14158641.html