LeetCode/solutions/89. Gray Code.md

98 lines
3.3 KiB
Markdown
Raw Normal View History

2019-03-21 06:50:31 +00:00
# [89. Gray Code](https://leetcode.com/problems/gray-code/)
# 思路
## 思路一
就按照题目的意思进行模拟用数组res和一个set来记录已经产生的结果我们从0开始遍历其二进制每一位对其取反
然后看其是否在set中出现过如果没有我们将其加入set和结果res中然后再递归对这个数进行刚刚的操作这样就可以得到所有的格雷码了。
## 思路二
如果对格雷码(可参考[维基百科](https://zh.wikipedia.org/wiki/%E6%A0%BC%E9%9B%B7%E7%A0%81))熟悉的话这题其实就是将二进制转换为格雷码,
举个例子3位的格雷码和二进制如下所示:
```
Int Grey Code Binary
0    000 000
1    001 001
2    011 010
3    010 011
4    110 100
5    111 101
6    101 110
7    100 111
```
参考维基百科及[这篇博客](http://www.omegaxyz.com/2017/11/16/grayandbi/)可很容易地写出代码。
2019-03-21 15:35:37 +00:00
## 思路三(最快)
2020-06-24 12:19:06 +00:00
参考[维基百科](https://zh.wikipedia.org/wiki/%E6%A0%BC%E9%9B%B7%E7%A0%81#%E9%8F%A1%E5%B0%84%E6%8E%92%E5%88%97)我们知道,**格雷码是按照镜面排列的**n位元的格雷码可以从n-1位元的格雷码以上下镜射后加上新位元的方式快速的得到如下图所示。
2019-03-21 15:35:37 +00:00
![graycode](http://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Binary-reflected_Gray_code_construction.svg/250px-Binary-reflected_Gray_code_construction.svg.png)
2020-06-24 12:19:06 +00:00
可以在前面加上新位元如上图绿色所示这样就和思路二产生的一样了也可以在后面添加新位元也是满足要求的相邻两个编码只有一个bit不同
2019-03-21 15:35:37 +00:00
2019-03-21 06:50:31 +00:00
# C++
## 思路一
``` C++
class Solution {
private:
void helper(vector<int> &res, set<int> &s, int code, int n){
s.insert(code);
res.push_back(code);
for(int i = 0; i < n; i++){
int mask = (1 << i);
int t = code;
if((t & mask) == 0) // 第i位是0
t |= mask; // 把第i位变成1
else // 第i位是1
t &= ~mask; // 把第i位变成0
if(s.count(t)) continue;
helper(res, s, t, n);
break;
}
}
public:
vector<int> grayCode(int n) {
vector<int> res;
set<int>s;
helper(res, s, 0, n);
return res;
}
};
```
## 思路二
``` C++
class Solution {
public:
vector<int> grayCode(int n) {
vector<int> res;
for (int i = 0; i < pow(2,n); ++i) {
res.push_back((i >> 1) ^ i); // ^ 是异或的意思
}
return res;
}
};
```
2019-03-21 15:35:37 +00:00
## 思路三
``` C++
class Solution {
public:
vector<int> grayCode(int n) {
2020-06-24 12:19:06 +00:00
vector<int>res{0};
for(int b = 0; b < n; b++){
for(int i = res.size() - 1; i >= 0; i--) // 镜面复制
res.push_back(res[i]);
int half_size = res.size() >> 1;
for(int i = 0; i < half_size; i++){
// 在前面添加新位元
res[i + half_size] += (1 << b);
// 在后面添加新位元
// res[i] <<= 1;
// res[i + half_size] = (res[i + half_size] << 1) + 1;
}
2019-03-21 15:35:37 +00:00
}
return res;
}
};
```