l1 问题描述
对于给定的正整数n,格雷码为满足如下条件的一个编码序列:
- 序列由2n个编码组成,每个编码都是长度为n的二进制位串。
- 序列中无相同的编码。
- 序列中位置相邻的两个编码恰有一位不同。
例如:n=4时的格雷码为:
0 0 0 0
0 0 0 1
0 0 1 1
0 0 1 0
0 1 1 0
0 1 1 1
0 1 0 1
0 1 0 0
1 1 0 0
1 1 0 1
1 1 1 1
1 1 1 0
1 0 1 0
1 0 1 1
1 0 0 1
1 0 0 0
设计求格雷码的递归算法并实现。
l2 实现思路
文件里先放0000,0001. 每次都倒序读取文件内内容,并修改高一位为1,如:0001->0011,0010->0110. 随后顺序写入文件.
l3 源代码
l3-1 倒序获取文件夹字符串
public void getStrBuilder(int offset) throws IOException {
RandomAccessFile rf = null;
int n=LENTH;
rf = new RandomAccessFile(FILEPATH, "r");
long len = rf.length();
long start = rf.getFilePointer();//开始位置
long cursor = start + len - 1;//结尾位置
rf.seek(cursor);
/*cursor设为最后一句的开始位置*/
if(rf.read()=='\n') {
cursor-=n;
}
else {
cursor-=n-1;
}
int from=offset;
int to = from +1;
while (cursor >= 0) {
rf.seek(cursor);
cursor-=n+1;//每句开头
line=rf.readLine();
sBuilder.append(line).append('\n');
sBuilder.replace(from, to, "1");//修改from处 为 1
from += n+1;
to =from+1;
}
}
函数用法:
- seek(cursor):移动文件指针,从0开始
- readline():读取整行,从当前指针开始,直到碰到
\n
,返回值:字符串(不含\n
) - replace(from, to, string):替代从from到to前一位的字符串为string.如:replace(1,3,”111”):”0000”->”01110”
l3-2 递归修改0->1
public void grayCode(int offset) throws IOException {
getStrBuilder(offset);//反向读取文件后的StringBuilder
FileWriter fileWriter = new FileWriter(FILEPATH,true);
fileWriter.write(sBuilder.toString());
//flush()仅仅是刷新缓冲区(一般写字符时要用,因为字符是先进入的缓冲区),流对象还可以继续使用
fileWriter.flush();
//sBuilder清空
sBuilder.delete(0, sBuilder.length());
offset--;
if(offset>=0) {
grayCode(offset);
}
}
函数用法:
- delete(1,2): 如:”12345”->”1345”
- flush()仅仅是刷新缓冲区(一般写字符时要用,因为字符是先进入的缓冲区),流对象还可以继续使用
- close()关闭流对象,但是先刷新一次缓冲区,关闭之后,流对象不可以继续再使用了。
l4 完整代码
https://github.com/waddless/courses/tree/master/%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90/GrayCode