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因此所转换为之格雷码为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——陈瑶师姐面试时候要用回溯算法的更多相关文章
- [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 ...
随机推荐
- selenium - webdriver - Keys类(键盘操作)
Keys()类提供了键盘上几乎所有按键的方法,这个类可用来模拟键盘上的按键,包括各种组合键,如 Ctrl+A, Ctrl+X,Ctrl+C, Ctrl+V 等等 from selenium impor ...
- MongoDB插入数据的3种方法
insert()方法: 下面是在inventory集合中插入一个三个字段的文档: db.inventory.insert( { _id: 10, type: "misc", ite ...
- 牛客练习赛42 出题的诀窍(数学+hash)
出题的诀窍 题目链接:https://ac.nowcoder.com/acm/contest/393/C 题解: 由于他是在每一行选取一个元素,然后纵向来比较,这里行的顺序是不会影响的,所以我们将每一 ...
- ACM1558两线段相交判断和并查集
Segment set Problem Description A segment and all segments which are connected with it compose a seg ...
- HDU1260DP
Tickets Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- tp if condition in_array用法
<if condition="in_array($vo['status'],[3])"> <a href="javascript:void(0);&qu ...
- [洛谷P3401] 洛谷树
洛谷题目连接:洛谷树 题目背景 萌哒的Created equal小仓鼠种了一棵洛谷树! (题目背景是辣鸡小仓鼠乱写的QAQ). 题目描述 树是一个无环.联通的无向图,由n个点和n-1条边构成.树上两个 ...
- PHP日期时间操作
一.设置时区 date_default_timezone_set('PRC'); 二.获取当前时间的 Unix 时间戳(格林威治时间 1970 年 1 月 1 日 00:00:00到当前时间的秒数)和 ...
- ssh 远程执行命令简介
在写这篇博客之前,我google了一堆相关文章,大都是说修改/etc/sudoers,然后NOPASSWD:指定的cmd,但是真心不管用,没有远程虚拟终端这个方法就是浮云,ubuntu10.04 se ...
- 51nod 1766 树上的最远点对——线段树
n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j& ...