前几天做某公司笔试题的时候竟然忘了什么是格雷码,导致一道大题的空白。现在有点时间把它写出来了。纪念一下。
什么是格雷码?
下面一段来自百度百科:
在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等)。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免这种错误。格雷码有多种编码形式。
由此可见,使用格雷码可以让数字电路的变化趋于稳定。
那么格雷码有什么规律呢?当用一个二进制表示格雷码时,也就是n=1时,格雷码只有0,1;
n=2时,格雷码是:00,01,11,10;
n=3时,格雷码是:000,001,011,010,110,111,101,100;
由此可见,格雷码都有一个普遍规律:
第一:格雷码的个数为2的n次方。如n=3时,有8个格雷码。
第二:格雷码的最高位有规律,前面一半为0,后面一半为1;
第三:格雷码除去最高位后,是对称的。10对10,11对11.而且由n-1的格雷码组成。
上面三点规律可以从下图看出:
以上可知,只要用个递归就可实现。
下面是实现代码:
import java.io.*;
import java.util.Scanner;
public class N_gray {
public static void main(String[] args){
//难道java中输入一个整数要经历很多东西吗?
Scanner sc=new Scanner(System.in);
String n=sc.nextLine();
int N=Integer.parseInt(n);
StringBuffer[] gray_code=get_gray(N);
for(int i=0;i<gray_code.length;i++){
System.out.println(gray_code[i]);
}
}
public static StringBuffer[] get_gray(int n){
int length=(int)Math.pow(2, n);
StringBuffer[] gray_code=new StringBuffer[length];
if(n==1){
gray_code[0]=new StringBuffer("0");
gray_code[1]=new StringBuffer("1");
}
else{
StringBuffer[] temp=get_gray(n-1);
for(int i=0;i<length;i++){
//如果用=,只是传引用,所以对gray_code[i]插值的时候会影响temp,从而导致最后的结果错误。
//gray_code[i]=temp[i%(length/2)];
if(i<(length/2)){
gray_code[i]=new StringBuffer((temp[i]));
gray_code[i].insert(0, "0");
}
else{
gray_code[i]=new StringBuffer((temp[length-i-1]));
gray_code[i].insert(0, "1");
}
}
}
return gray_code;
}
}