一,格雷码

力扣 89. 格雷编码

n 位格雷码序列 是一个由 2n 个整数组成的序列,其中:

每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 1)

第一个整数是 0

一个整数在序列中出现 不超过一次

每对 相邻 整数的二进制表示 恰好一位不同 ,且

第一个 和 最后一个 整数的二进制表示 恰好一位不同

给你一个整数 n ,返回任一有效的 n 位格雷码序列 。

示例 1:

输入:n = 2

输出:[0,1,3,2]

解释:

[0,1,3,2] 的二进制表示是 [00,01,11,10] 。

- 00 和 01 有一位不同

- 01 和 11 有一位不同

- 11 和 10 有一位不同

- 10 和 00 有一位不同

[0,2,3,1] 也是一个有效的格雷码序列,其二进制表示是 [00,10,11,01] 。

- 00 和 10 有一位不同

- 10 和 11 有一位不同

- 11 和 01 有一位不同

- 01 和 00 有一位不同

示例 2:

输入:n = 1

输出:[0,1]


提示:

1 <= n <= 16

思路:

利用分治算法,由n位格雷码可以直接得到n+1位格雷码。

编码技术大全_进制

代码:

//翻转vector
template<typename T>
vector<T> frev(const vector<T>& v)
{
vector<T> ans;
ans.resize(v.size());
for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
return ans;
}
//vector加一个数
template<typename T1, typename T2>
void fjia(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
}
//2个vector拼接起来
template<typename T>
vector<T> join(const vector<T>& v1, const vector<T>& v2)
{
vector<T>ans(v1.size() + v2.size());
copy(v1.begin(), v1.end(), ans.begin());
copy(v2.begin(), v2.end(), ans.begin() + v1.size());
return ans;
}
class Solution {
public:
vector<int> grayCode(int n) {
if (n <= 0) {
return vector<int>(1);
}
vector<int> v = grayCode(n - 1);
vector<int> v2 = frev(v);
fjia(v2, 1 << n - 1);
return join(v, v2);
}
};

2,格雷码简介

上面的题目已经把格雷码的要求说的很清楚了,输出解释里面也提到了格雷码不是唯一的。

我上面代码得到的是最典型的格雷码(和上面图片内相同),一般格雷码默认指的就是这种。

对于典型格雷码,可以直接算出每个数的格雷码:

对于n位二进制数a1 a2 ... an,表示成n位格雷码g1 g2 ... gn,

编码技术大全_进制_02,这里的+表示异或

例如11的四位二进制是1011,则格雷码是1110,即14

用数学归纳法很容易证明这个规律是对的。

3,格雷码和九连环


九连环按照每个环在上面就是1在下面就是0编号,可以得到一个九位二进制数。


每次只能修改一位(一个环),最终的目标是变成000000000


神奇的是,九连环的最快解法(即没有无效操作,不考虑最后2个环一起操作)就是在从2^9-1到0的一个遍历。


grayToInt(511,9)的结果是101010101,即341,所以九连环需要341步。


也可以根据gray函数直接把九连环的步骤打出来:


void gray(int n, int k)
{
vector<int>v;
for (int i = 0; i < k; i++) {
v.push_back(n % 2);
n /= 2;
}
v.push_back(0);
for (int i = k; i; i--)cout << (v[i] ^ v[i - 1]);
cout << " ";
}

int main()
{
for (int n = 341; n >= 0; n--) {
gray(n, 9);
if (n % 5 == 0)cout << endl;
}
return 0;
}

输出:


111111111  111111110

111111010  111111011  111111001  111111000  111101000

111101001  111101011  111101010  111101110  111101111

111101101  111101100  111100100  111100101  111100111

111100110  111100010  111100011  111100001  111100000

110100000  110100001  110100011  110100010  110100110

110100111  110100101  110100100  110101100  110101101

110101111  110101110  110101010  110101011  110101001

110101000  110111000  110111001  110111011  110111010

110111110  110111111  110111101  110111100  110110100

110110101  110110111  110110110  110110010  110110011

110110001  110110000  110010000  110010001  110010011

110010010  110010110  110010111  110010101  110010100

110011100  110011101  110011111  110011110  110011010

110011011  110011001  110011000  110001000  110001001

110001011  110001010  110001110  110001111  110001101

110001100  110000100  110000101  110000111  110000110

110000010  110000011  110000001  110000000  010000000

010000001  010000011  010000010  010000110  010000111

010000101  010000100  010001100  010001101  010001111

010001110  010001010  010001011  010001001  010001000

010011000  010011001  010011011  010011010  010011110

010011111  010011101  010011100  010010100  010010101

010010111  010010110  010010010  010010011  010010001

010010000  010110000  010110001  010110011  010110010

010110110  010110111  010110101  010110100  010111100

010111101  010111111  010111110  010111010  010111011

010111001  010111000  010101000  010101001  010101011

010101010  010101110  010101111  010101101  010101100

010100100  010100101  010100111  010100110  010100010

010100011  010100001  010100000  011100000  011100001

011100011  011100010  011100110  011100111  011100101

011100100  011101100  011101101  011101111  011101110

011101010  011101011  011101001  011101000  011111000

011111001  011111011  011111010  011111110  011111111

011111101  011111100  011110100  011110101  011110111

011110110  011110010  011110011  011110001  011110000

011010000  011010001  011010011  011010010  011010110

011010111  011010101  011010100  011011100  011011101

011011111  011011110  011011010  011011011  011011001

011011000  011001000  011001001  011001011  011001010

011001110  011001111  011001101  011001100  011000100

011000101  011000111  011000110  011000010  011000011

011000001  011000000  001000000  001000001  001000011

001000010  001000110  001000111  001000101  001000100

001001100  001001101  001001111  001001110  001001010

001001011  001001001  001001000  001011000  001011001

001011011  001011010  001011110  001011111  001011101

001011100  001010100  001010101  001010111  001010110

001010010  001010011  001010001  001010000  001110000

001110001  001110011  001110010  001110110  001110111

001110101  001110100  001111100  001111101  001111111

001111110  001111010  001111011  001111001  001111000

001101000  001101001  001101011  001101010  001101110

001101111  001101101  001101100  001100100  001100101

001100111  001100110  001100010  001100011  001100001

001100000  000100000  000100001  000100011  000100010

000100110  000100111  000100101  000100100  000101100

000101101  000101111  000101110  000101010  000101011

000101001  000101000  000111000  000111001  000111011

000111010  000111110  000111111  000111101  000111100

000110100  000110101  000110111  000110110  000110010

000110011  000110001  000110000  000010000  000010001

000010011  000010010  000010110  000010111  000010101

000010100  000011100  000011101  000011111  000011110

000011010  000011011  000011001  000011000  000001000

000001001  000001011  000001010  000001110  000001111

000001101  000001100  000000100  000000101  000000111

000000110  000000010  000000011  000000001  000000000

————————————————

版权声明:本文为CSDN博主「csuzhucong」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。