【筆記】JavaScript版數據結構與算法——基礎算法之“數組類”(89. 格雷編碼)


格雷編碼

二進制運算

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;
};

在這裏插入圖片描述

拓展

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章