Gray Code——陈瑶师姐面试时候要用回溯算法
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位二进制的码字,从右到左,以0到n-1编号
- 如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变)
- 例如:二进制码0101,为4位数,所以其所转为之格雷码也必为4位数,因此可取转成之二进位码第五位为0,即0 b3 b2 b1 b0。
0 xor 0=0,所以g3=00 xor 1=1,所以g2=11 xor 0=1,所以g1=10 xor 1=1,所以g0=1因此所转换为之格雷码为0111class 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——陈瑶师姐面试时候要用回溯算法的更多相关文章
- [LeetCode] Gray Code 格雷码
		The gray code is a binary numeral system where two successive values differ in only one bit. Given a ... 
- 【LeetCode】Gray Code
		Gray Code The gray code is a binary numeral system where two successive values differ in only one bi ... 
- Gray Code
		Gray Code The gray code is a binary numeral system where two successive values differ in only one bi ... 
- 【leetcode】Gray Code (middle)
		The gray code is a binary numeral system where two successive values differ in only one bit. Given a ... 
- [LintCode] Gray Code 格雷码
		The gray code is a binary numeral system where two successive values differ in only one bit. Given a ... 
- 44. Decode Ways  &&  Gray Code
		Decode Ways A message containing letters from A-Z is being encoded to numbers using the following ma ... 
- LeetCode——Gray Code
		Description: The gray code is a binary numeral system where two successive values differ in only one ... 
- LeetCode:Gray Code(格雷码)
		题目链接 The gray code is a binary numeral system where two successive values differ in only one bit. Gi ... 
- [LeetCode]题解(python):089 Gray Code
		题目来源 https://leetcode.com/problems/gray-code/ The gray code is a binary numeral system where two suc ... 
随机推荐
- jquery 操作实例一
			<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ... 
- 清北学堂模拟赛d6t6 棋盘迷宫
			3.棋盘迷宫(boardgame.pas/c/cpp)(boardgame.in/out)时间限制:5s/空间限制:256M[题目描述]小 A 和小 Z 是非常要好的朋友, 而且他们都对迷宫游戏非常有 ... 
- javascript中不易分清的slice,splice和split三个函数
			1.slice(数组) 用法:array.slice(start,end) 解释:该方法是对数组进行部分截取,并返回一个数组副本:参数start是截取的开始数组索引,end参数等于你要取的最后一个字符 ... 
- async/await 里的并行和串行
			我们在使用 async/await 语法时,有时会这样用: function getName () { return new Promise((resolve, reject)=>{ setTi ... 
- CSS图片宽度设置百分比 , 高度同宽度相同
			在图片长宽不相等的情况下,想将长宽设置为相等并且自适应屏幕,可以通过 js 的方式进行设置并通过监听 resize 来实时更新,但是这种方式很麻烦. 这里通过 css 来达到我们想要的效果: < ... 
- 整数中1出现的次数(从1到n整数中1出现的次数)
			整数中1出现的次数(从1到n整数中1出现的次数) 题目描述 求出1 ~ 13的整数中1出现的次数,并算出100 ~ 1300的整数中1出现的次数?为此他特别数了一下1 ~ 13中包含1的数字有1.10 ... 
- 2050年这些职业将逐渐被AI(人工智能)取代
			耳熟能详的人工智能 深蓝Deep Blue是美国IBM公司生产的一台超级国际象棋电脑,重1270公斤,有32个大脑(微处理器),每秒钟可以计算2亿步."深蓝”输入了一百多年来优秀棋手的对 ... 
- git概论
			感谢:http://www.cnblogs.com/atyou/archive/2013/03/11/2953579.html git,一个非常强大的版本管理工具.Github则是一个基于Git的日益 ... 
- LightOJ 1306 - Solutions to an Equation 裸EXGCD
			本题是极其裸的EXGCD AX+BY+C=0 给你a b c 和x与y的区间范围,问你整数解有几组 作为EXGCD入门,题目比较简单 主要需要考虑区间范围的向上.向下取整,及正负符号的问题 问题是这正 ... 
- 奇偶排序Odd-even sort
			又一个比较性质的排序,基本思路是奇数列排一趟序,偶数列排一趟序,再奇数排,再偶数排,直到全部有序 举例吧, 待排数组[6 2 4 1 5 9] 第一次比较奇数列,奇数列与它的邻居偶数列比较,如6和2比 ... 
