算法---输出n 位格雷码中的 k 号二进制串

        最近,在洛谷里刷题时遇见了关于格雷码的题: 

        像往常一样,我去题解里看看大佬们的方法是什么样的,

        偶然间,我看到第一位的大佬巧妙的方法:

         短短8行代码,却让人摸不着头脑。

        于是,在寻找和学习了许多资料后,写下这篇文章当作笔记。


        首先,通过读题以及简单的观察规律,我们可以知道输出n 位格雷码中的 k 号二进制串要求我们输出的是从0开始第k个格雷码,而且该格雷码位数应该是n位(如输出4位的第四个格雷码便是 0110,3位便是110,5位的第14个格雷码是01001)

        再回过神观看这位大佬的题解,运用的结论是第k个格雷码Gk = k xor (k>>1)(k从0数起),即 G_{k}= k \oplus \left \lfloor \frac{k}{2} \right \rfloor= k \oplus (k>>1) 

        但是,这结论又是怎么来的呢?还是令人费解。

        在学习了几篇文章下,我发现这给结论正是二进制转格雷码的方法,于是恍然大悟。

         原理: 若二进制码表示为: B[N-1]B[N-2]...B[2]B[1]B[0];

         相应地, 则二进制格雷码表示为: G[N-1]G[N-2]...G[2]G[1]G[0].

         其中最高位保留: G[N-1] = B[N-1];

         其他各位: G[i] = B[i+1] xor B[i]. (i = 0, 1, 2, ..., n-2)


        但是,至于这个原理如何证明,我找到了这篇文章:

        第k个格雷码为k xor (k>>1)的简单理解证明

        以下为他的证明:

        我们假设不知道这个结论,我们寻找一种结论来用k表示Gk。

        首先考虑  G_{k} \oplus G_{k+1},这个式子必须只有一位为1。 

        我们进行分类讨论:

        ① 如果k的最低位为0,则k+1最低位为1,没有产生进位,此时要使式子只有一位为1,将k和k+1异或即可,G_{k} \oplus G_{k+1} = k \oplus (k+1) = 1

        由这种情况我们可以假设 ,这在第一种情况成立,然而在第二种情况不成立。

        ② 如果k的最低位为1,则k+1最低位为0,此时发生了进位。

        举个例子,

              k = (110100111)_{2}

              k+1 = (110101000)_{2}

        则 k \oplus (k+1) = (000001111)_{2}

        我们如何改进 G_{k} = k 这个公式,使得这个公式既符合第一种情况又符合第二种情况呢? 

        只要把1111异或上0111就得到了1000。

        我们容易发现  k \oplus (k+1)>>1 = (000000111)_{2} = (k>>1) \oplus ((k+1)>>1)

        由异或运算的性质得到   

         k \oplus (k+1) \oplus (k>>1) \oplus ((k+1)>>1) = k \oplus (k>>1) \oplus (k+1) \oplus ((k+1)>>1) = (000001000)_{2}

         观察容易知道我们若设 G_{k}= k \oplus (k>>1) ,则符合第二种情况,同时也符合第一种情况。 

        这样就得到了这个符合全部情况的结论G_{k}= k \oplus \left \lfloor \frac{k}{2} \right \rfloor= k \oplus (k>>1)


        以上就是怎样转换格雷码,但是最后一句代码好像也需要简单分析一下。

while(~--n) cout<<(k>>n&1);

        首先,看这个循环条件 ~--n,如果n我们输入的为3,这个条件中的值会是-3,-2,-1然后终止while运行。这部分没什么问题,但是k>>n&1是如何逐位输出i位的格雷码呢?

        我们可以看出,k>>n的这几次分别会将n位中每一位移到其最低位,并与1进行按位与运算.因此可以通过这种方式格雷码的前k位.

(如00101 >>3 & 00001= 0,  00101 >> 2 & 00001 =1,  00101>>1&00001 = 0,  00101 >> 0 & 1 =1 所以当k=6, n=4,k^= k>>1 后k=5时, 4位的第六个格雷码便是0101)

        当然,在大佬给出这些算法前,我怎么想也想不出来.

        看来我还需进行很大的努力.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值