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. Nginx配置解析

    #运行用户,默认即是nginx,可不设置 #user nobody; #nginx进程,一般设置为和cpu核数一样 worker_processes 1; #;单个后台worker process进程 ...

  2. HashMap & SparseArray & ArrayMap 简单说明

    HashMap 使用有限一维拉链数组存储结构,鉴于所用Entry结构{key, value, nextExtry},Key的hash值用于取余获得所属的数组行下标,通过链表方式顺序存放所有余数相同的各 ...

  3. hdu4109 topsort

    Problem Description Ali has taken the Computer Organization and Architecture course this term. He le ...

  4. Spring框架介绍和原理

    SpringMVC框架介绍 1) Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面. Spring 框架提供了构建 Web 应用程序的全功 ...

  5. uva 11424

    uva 11424 GCD - Extreme (I) 题意:思路:(见http://www.cnblogs.com/Duahanlang/p/3184994.html ) 差别在于数据规模和时间,其 ...

  6. Qt中内存泄露和退出崩溃的问题 delete

    Qt中帮程序员做了一些内存回收的事情,但正因为这些反而让对此不熟悉的人会屡屡犯错. 收录一篇不错的文章: 在C++中学习过程中,我们都知道: delete 和 new 必须 配对使用(一 一对应):d ...

  7. Python os.walk文件遍历

    os.walk(top, topdown=True, onerror=None, followlinks=False) 可以得到一个三元tupple(dirpath, dirnames, filena ...

  8. 简单的异步HTTP服务端和客户端

    /// <summary> /// 异步Http服务器 /// </summary> class AsyncHttpServer { readonly HttpListener ...

  9. MVC4 AspNet MVC下的Ajax / 使用JQuery做相关的Ajax请求

    源码参考:链接:http://pan.baidu.com/s/1pKhHHMj  密码:mkr4 1:新建-->项目-->Web-->ASP.NET MVC 4 Web 应用程序.命 ...

  10. px,em,rem字体单位

    1.px像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的.(引自CSS2.0手册) 2.em是相对长度单位.相对于当前对象内文本的字体尺寸,em存在值继承问题. 浏览器的默认字 ...