格雷編碼
二進制運算
1.題目
89. 格雷編碼 - 力扣(LeetCode)
格雷編碼是一個二進制數字系統,在該系統中,兩個連續的數值僅有一個位數的差異。
給定一個代表編碼總位數的非負整數 n,打印其格雷編碼序列。即使有多個不同答案,你也只需要返回其中一種。
格雷編碼序列必須以 0 開頭。
示例 1:
輸入: 2
輸出: [0,1,3,2]
解釋:
00 - 0
01 - 1
11 - 3
10 - 2
對於給定的 n,其格雷編碼序列並不唯一。
例如,[0,2,3,1] 也是一個有效的格雷編碼序列。
00 - 0
10 - 2
11 - 3
01 - 1
示例 2:
輸入: 0
輸出: [0]
解釋: 我們定義格雷編碼序列必須以 0 開頭。
給定編碼總位數爲 n 的格雷編碼序列,其長度爲 2n。當 n = 0 時,長度爲 20 = 1。
因此,當 n = 0 時,其格雷編碼序列爲 [0]。
2.思路分析
見題解
3.所用到的方法
位移運算符 <<、>>
異或運算符 ^
1.交換律:a ^ b ^ c <=> a ^ c ^ b
2.任何數於0異或爲任何數 0 ^ n => n
3.相同的數異或爲0: n ^ n => 0
4.題解及優化
我的題解(!!!)
觀看了一個簡短的python解法如下:
class Solution(object):
def grayCode(self, n):
"""
:type n: int
:rtype: List[int]
"""
n=1<<n
res=[]
for i in range(n):
res.append(i^(i>>1)) #2進制轉換格雷碼
return res
感覺這纔是我想要的答案,使用js模仿如下
var grayCode = function (n) {
n = 1 << n
let res = []
for (let i = 0; i < n; i++) {
res.push(i ^ (i >> 1)) // 2進制轉換格雷碼
}
return res
}
還不錯
課程解法
var grayCode = function (n) {
// 遞歸函數,用來算輸入爲n的格雷編碼序列
let make = (n) => {
if (n === 0) {
return [0]
} else if (n === 1) {
return ['0', '1']
} else {
let prev = make(n - 1)
let result = []
let max = Math.pow(2, n) - 1
for (let i = 0, len = prev.length; i < len; i++) {
result[i] = `0${prev[i]}`
result[max - i] = `1${prev[i]}`
}
return result
}
}
return make(n).map(item => parseInt(item, 2))
}
其他小夥伴的解法
在十進制數組中找規律(1)
比如輸入3,結果是[0,1,3,2,6,7,5,4]
總數就是2^3=8;
把它分成兩部分,[0,1,3,2]和[6,7,5,4],
然後把[0,1,3,2]複製一份,倒過來[2,3,1,0]
[6,7,5,4]減去[2,3,1,0]等於[4,4,4,4]=2的n-1次方遍歷4次!
var grayCode = function(n) {
let res = [0]
let right
for (let i = 1; i <= n; i++) {
right = [...res].reverse().map((item) => item + Math.pow(2, i - 1))
res = res.concat(right)
}
return res
}
在十進制數組中找規律(2)
n = 0, [0]
n = 1, [0,1] //新的元素1,爲0+2^0
n = 2, [0,1,3,2] // 新的元素[3,2]爲[0,1]->[1,0]後分別加上2^1
n = 3, [0,1,3,2,6,7,5,4] // 新的元素[6,7,5,4]爲[0,1,3,2]->[2,3,1,0]後分別加上2^2->[6,7,5,4]
最終肯定會輸出整個數組, 0 - 2^n-1
var grayCode = function(n) {
let res = [0]
let right
let i = 1
while (i <= n) {
right = res
.slice(0)
.reverse()
.map((item) => item + Math.pow(2, i - 1))
res = res.concat(right)
i++
}
return res
}
轉碼
時間複雜度: O(2^N)
空間複雜度: O(1)
var grayCode = function(n) {
let ans = [];
let head = 1;
ans.push(0);
for(let i = 0; i < n;i ++) {
let len = ans.length - 1;
for(let j = len; j >=0; j--) {
ans.push(head + ans[j])
}
// 位運算: b1等於b1乘以2的1次方
head <<=1;
}
return ans;
};
拓展