The gray code is a binary numeral system where two successive values differ in only one bit.

Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.

For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:

00 - 0
01 - 1
11 - 3
10 - 2

Note:
For a given n, a gray code sequence is not uniquely defined.

For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.

For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.

这里没用回溯算法,而是看到网上运用了一些小技巧,直接用二进制码转化成了格雷码。

后注:转格雷码简而言之就是从最右边一位起,依次将每一位与左边一位异或(XOR),作为对应格雷码该位的值,最左边一位不变(相当于左边是0)。

异或转换

二进制码→格雷码(编码)
此方法从对应的n位二进制码字中直接得到n位格雷码码字,步骤如下:
  1. 对n位二进制的码字,从右到左,以0到n-1编号
  2. 如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变)
  3. 例如:二进制码0101,为4位数,所以其所转为之格雷码也必为4位数,因此可取转成之二进位码第五位为0,即0 b3 b2 b1 b0。
    0 xor 0=0,所以g3=0
    0 xor 1=1,所以g2=1
    1 xor 0=1,所以g1=1
    0 xor 1=1,所以g0=1
    因此所转换为之格雷码为0111

    class Solution {
    public:
    vector<int> grayCode(int n) {
    vector<int> res;
    for (int i = ; i < pow(,n); ++i) {
    res.push_back((i / ) ^ i);
    }
    return res; }
    };

    数学解释: 从第0个开始,第i个gray code为:(i>>1)^i(这个应该是最容易理解的)

     class Solution
    {
    public:
    /*
    * for reference: http://en.wikipedia.org/wiki/Gray_code.*/
    vector<int> grayCode(int n)
    {
    vector<int> ret;
    int size = << n;
    for(int i = ; i < size; ++i)
    ret.push_back((i >> )^i);
    return ret;
    }
    };

这道题原来陈瑶师姐面试时需要用递归来做,而我在腾讯实习生面试时再次碰到了这道题,其实利用递归也很简单的。具体思路了参考了以下博客:

http://www.tuicool.com/articles/QrYFb2J

简介

在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为 格雷码 (Gray Code), 另外由于最大数与最小数之间也仅一位数不同 ,即“首尾相连”,因此又称循环码或反射码 。在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位 的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等)。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免 这种错误。格雷码有多种编码形式。

格雷码(Gray Code)曾用过Grey Code、葛莱码、格莱码、戈莱码、循环码、反射二进制码、最小差错码等名字,它们有的不对,有的易与其它名称混淆,建议不要再使用这些曾用名。

生成格雷码

格雷码(Gray Code)是一个数列集合,每个数使用二进位来表示,假设使用n位元来表示每个数字,任两个数之间只有一个位元值不同。

例如以下为3位元的格雷码: 000 001 011 010 110 111 101 100 。

如果要产生 n位 元的格雷码 ,那么 格雷码的 个数为2^n .

假设原始的值从0开始,格雷码 产生的规律 是:

第一步,改变最右边的位元值;

第二步,改变右起第一个为1的位元的左边位元;

第三步,第四步重复第一步和第二步,直到所有的格雷码产生完毕(换句话说,已经走了(2^n) - 1 步)。

用一个 例子 来说明:

假设产生3位元的格雷码,原始值位 000

第一步:改变最右边的位元值: 001

第二步:改变右起第一个为1的位元的左边位元: 011

第三步:改变最右边的位元值: 010

第四步:改变右起第一个为1的位元的左边位元: 110

第五步:改变最右边的位元值: 111

第六步:改变右起第一个为1的位元的左边位元: 101

第七步:改变最右边的位元值: 100

如果按照这个规则来生成格雷码,是没有问题的,但是这样做太复杂了。如果仔细观察格雷码的结构,我们会有以下发现:

1、除了最高位(左边第一位),格雷码的位元完全上下对称(看下面列表)。比如第一个格雷码与最后一个格雷码对称(除了第一位),第二个格雷码与倒数第二个对称,以此类推。

2、 最小的重复单元是 0 , 1

0 00

0 01

0 11

0 10

1 10

1 11

1 01

1

00

所以,在实现的时候,我们完全可以利用递归,在每一层前面加上0或者1,然后就可以列出所有的格雷码。

比如:

第一步:产生 0, 1 两个字符串。

第二步:在第一步的基础上,每一个字符串都加上0和1,但是每次只能加一个,所以得做两次。这样就变成了 00,01,11,10 (注意对称)。

第三步:在第二步的基础上,再给每个字符串都加上0和1,同样,每次只能加一个,这样就变成了 000,001,011,010,110,111,101,100。

好了,这样就把3位元格雷码生成好了。

如果要生成4位元格雷码,我们只需要在3位元格雷码上再加一层0,1就可以了: 0000,0001,0011,0010,0110,0111,0101,0100,1100,1101,1110,1010,0111,1001,1000.

也就是说, n位元格雷码是基于n-1位元格雷码产生的。

以下是在自己的PC上根据腾讯的要求写的代码:

(以下代码并不能通过leetcode,因为其返回值不满足其输出要求)

/*

在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同, 则称这种编码为格雷码(Gray Code),请编写一个函数,使用递归的方法生成N位的格雷码。

给定一个整数n,请返回n位的格雷码,顺序为从0开始。
测试样例: 1 返回:["0","1"]
http://www.tuicool.com/articles/QrYFb2J
*/
#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
vector<string> graycode(int N);
int main()
{
vector<string> res;
int n;
scanf("%d",&n);
if(n<=)
return ;
long long Num=<<n;
res=graycode(n);
for(int i=;i<res.size();i++)
cout<<res[i]<<endl;
return ; }
vector<string> graycode(int N)
{
long long num=<<N;
vector<string> current(num,"");
if(N==)
{
current[]='';
current[]="";
return current;
}
vector<string> befor=graycode(N-);
for(int i=;i<befor.size();i++)
{
current[i]=""+befor[i];
current[num--i]=""+befor[i];
}
return current;
}

以下代码能通过leetcode的验证:

class Solution {
public:
    vector<int> grayCode(int n) {
        if(n<=0)
            return vector<int>(1,0);
        long long Num=1<<n;
        vector<int> res(Num,0);
        res=getGraycode(n);
        return res;
    }
     vector<int> getGraycode(int N)
     {
        long long num=1<<N;
        vector<int> current(num,0);
        if(N==1)
        {
            current[0]=0;
            current[1]=1;
            return current;
        }
        vector<int> befor=getGraycode(N-1);
        for(int i=0;i<befor.size();i++)
        {
            int c=1<<N-1;
            current[i]=befor[i];
            current[num-1-i]=c+befor[i];
        }
        return current;
     }
};

Gray Code——陈瑶师姐面试时候要用回溯算法的更多相关文章

  1. [LeetCode] Gray Code 格雷码

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  2. 【LeetCode】Gray Code

    Gray Code The gray code is a binary numeral system where two successive values differ in only one bi ...

  3. Gray Code

    Gray Code The gray code is a binary numeral system where two successive values differ in only one bi ...

  4. 【leetcode】Gray Code (middle)

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  5. [LintCode] Gray Code 格雷码

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  6. 44. Decode Ways && Gray Code

    Decode Ways A message containing letters from A-Z is being encoded to numbers using the following ma ...

  7. LeetCode——Gray Code

    Description: The gray code is a binary numeral system where two successive values differ in only one ...

  8. LeetCode:Gray Code(格雷码)

    题目链接 The gray code is a binary numeral system where two successive values differ in only one bit. Gi ...

  9. [LeetCode]题解(python):089 Gray Code

    题目来源 https://leetcode.com/problems/gray-code/ The gray code is a binary numeral system where two suc ...

随机推荐

  1. php ul li 分类

    <?phpfunction do_tree($arr,$pid){ echo "<ul>"; foreach ($arr as $key => $value ...

  2. mybatis 根据id批量删除的两种方法

    原文:https://blog.csdn.net/qq_40010745/article/details/81032218 mybatis 根据id批量删除的两种方法   第一种,直接传递给mappe ...

  3. Python通过PhantomJS获取JS渲染后的网页源代码

    新建一个文件,命名为test.js,内容如下: var page = require('webpage').create(), system = require('system'), address; ...

  4. luncence

    问题的提出: 我们在访问淘宝,京东这些商城系统的时候,我们可以随意的在文本框输入关键字就可以获取到所想要的信息或者相关的信息,那么我们到底是如何实现这个功能的呢,为什么可以随意的输入就可以显示相关的信 ...

  5. bzoj2428 [HAOI2006]均分数据 模拟退火

    [HAOI2006]均分数据 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 3434  Solved: 1091[Submit][Status][Dis ...

  6. 「模板」 01 Trie实现平衡树功能

    不想多说什么了.费空间,也不算太快,唯一的好处就是好写吧. #include <cstdio> #include <cstring> const int MAXN=100010 ...

  7. 【HDU】6012 Lotus and Horticulture (BC#91 T2)

    [算法]离散化 [题解] 答案一定存在于区间的左右端点.与区间左右端点距离0.5的点上 于是把所有坐标扩大一倍,排序(即离散化). 让某个点的前缀和表示该点的答案. 初始sum=∑c[i] 在l[i] ...

  8. jQuery清空表单方法

    $(':input', '#form1') .not(':button, :submit, :reset, :hidden') .val('') .removeAttr('checked') .rem ...

  9. 结合promise对原生fetch的两个then用法理解

    前言:该问题是由于看到fetch的then方法的使用,产生的疑问,在深入了解并记录对promise的个人理解 首先看一下fetch请求使用案例: 案例效果:点击页面按钮,请求当前目录下的arr.txt ...

  10. Apache2.4+Tomcat7 集群

    Apache2.4+Tomcat7 集群: 1.下载并安装相对应的软件 apache下载地址:http://httpd.apache.org/ 这里使用apache2.4 tomcat下载地址:htt ...