1. 程式人生 > >LeetCode——89. 格雷編碼(JavaScript)

LeetCode——89. 格雷編碼(JavaScript)

格雷編碼是一個二進位制數字系統,在該系統中,兩個連續的數值僅有一個位數的差異。

給定一個代表編碼總位數的非負整數 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]。

思路:

依次改變每位的0/1,看是否出現過,若出現過,則更新當前的數,並重新開始從第一位開始改變。

以 n=3 為例
設定一個 arr = [0,0,0],表示 0 的三位二進位制編碼,
設定一個set,用來儲存出現過的編碼,初始為 {’000‘},
設定一個res陣列,用來儲存結果序列,初始為 [0]
n = 3 時的格雷編碼序列長度應該為 2 的 3次方,即8.
當 res 長度小於 8 時開始迴圈,

while(res.length < 2 ** n) {
	// 設定一個臨時變數,temp
	let temp = arr.slice()	// .slice()是拷貝,修改temp不會對arr造成影響
// 開始依次改變每一位 for (let i = 0; i < n; i++) { temp[i] ^= 1 // 異或操作,1變0,0變1 let str = temp.join('') // str為二進位制編碼字串 若str在set中,則什麼都不發生, 若不在,則說明此編碼符合要求,要將此編碼加入set,還要計算此數字並加入res,最後更新arr為temp,break} }

還要寫一個根據二進位制編碼求得數字的函式:

  const strToNum = str => {
    let num = 0
    let len = str.length
    for
(let i = 0; i < len; i++) { if (str[i] === '1') { num += 2 ** (n-i-1) } } return num }

最終程式碼:

/**
 * @param {number} n
 * @return {number[]}
 */
var grayCode = function(n) {
  const strToNum = str => {
    let num = 0
    let len = str.length
    for (let i = 0; i < len; i++) {
      if (str[i] === '1') {
        num += 2 ** (n-i-1)
      }
    }
    return num
  }
  
  let res = [0]
  let arr = Array(n).fill(0)
  let set = new Set()
  set.add(arr.join(''))
  while (res.length < 2 ** n) {
    let temp = arr.slice()
    for (let i = 0; i < n; i++) {
      temp[i] ^= 1    // 異或操作,1變0,0變1 
      let str = temp.join('')
      if (set.has(str)) {
        temp[i] = arr[i]  // 若已存在,則變回去
      } else {
        set.add(str)
        res.push(strToNum(str))
        arr = temp
        break;
      }
    }
  }
  
  return res
};