var reverseBits = function (n) {
  let result = 0;
  for (let i = 0; i < 32; ++i) {
    result = (result << 1) + (n & 1);
    n >>= 1;
  }
  return result >>> 0;
};
題目要求要把二進制的 input n 做翻轉後,再轉成十進制作成 output
首先要先知道(左、右)位移位運算子、無符號右位移運算子:
const a = 5; // 00000000000000000000000000000101
const b = 2; // 00000000000000000000000000000010
console.log(a << b); // 00000000000000000000000000010100
// Expected output: 20
//-----------------------------------------------------------
const a = 5; //  00000000000000000000000000000101
const b = 2; //  00000000000000000000000000000010
const c = -5; //  11111111111111111111111111111011
console.log(a >> b); //  00000000000000000000000000000001
// Expected output: 1
console.log(c >> b); //  11111111111111111111111111111110
// Expected output: -2
//-----------------------------------------------------------
const a = 5; //  00000000000000000000000000000101
const b = 2; //  00000000000000000000000000000010
const c = -5; //  11111111111111111111111111111011
console.log(a >>> b); //  00000000000000000000000000000001
// Expected output: 1
console.log(c >>> b); //  00111111111111111111111111111110,差異在整個數字右移後,前面補上 b 個 0
// Expected output: 1073741822
然後是 Bitwise AND (&) :

知道這些之後,來理解下解法的程式碼:
result = (result << 1) + (n & 1); 可以拆成兩個階段看:
result += (n & 1); 取出最右邊的 bit,ex: 00101 取得最右邊 1result <<= 1; 往左移一個 bitresult = (result << 1) + (n & 1); 就是 0 + 1 = 01
n >>= 1; 則是捨棄掉已取得的最右邊 bit,ex: 00101 變成 00010
下次迴圈時: result = (result << 1) + (n & 1); 就是 10 + 0,n >>= 1; 則是捨棄掉已取得的最右邊 bit,ex: 00010 變成 00001
再下次迴圈時: result = (result << 1) + (n & 1); 就是 100 + 1,n >>= 1; 則是捨棄掉已取得的最右邊 bit,ex: 00000 變成 00000
以此類推,迴圈跑完,將 result 用 >>> 轉成 unsigned
時間複雜度: O(1)
空間複雜度: O(1)
https://youtu.be/UcoN6UjAI64?si=ePHwN2_weElexBTX
將數字做翻轉:
function reverse_a_number(n) {
  let reversedNum = 0;
  while (n !== 0) {
    reversedNum = reversedNum * 10 + (n % 10);
    n = Math.floor(n / 10);
  }
  return reversedNum;
}
const roman = new Map([
  ['M', 1000],
  ['CM', 900],
  ['D', 500],
  ['CD', 400],
  ['C', 100],
  ['XC', 90],
  ['L', 50],
  ['XL', 40],
  ['X', 10],
  ['IX', 9],
  ['V', 5],
  ['IV', 4],
  ['I', 1],
]);
var romanToInt = function (s) {
  let counter = 0;
  let result = 0;
  while (counter < s.length) {
    if (roman.get(s.slice(counter, counter + 2))) {
      result += roman.get(s.slice(counter, counter + 2));
      counter += 2;
    } else {
      result += roman.get(s.slice(counter, counter + 1));
      counter++;
    }
  }
  return result;
};
用 hashMap 去儲存各種 roman 字串的對應值再做比對。
時間複雜度: O(1)
空間複雜度: O(n)
/**
 * @param {number[]} w
 */
var Solution = function (w) {
  this.weights = [];
  this.sum = 0;
  for (let i = 0; i < w.length; i++) {
    this.sum += w[i];
    this.weights.push(this.sum);
  }
};
/**
 * @return {number}
 */
Solution.prototype.pickIndex = function () {
  const index = Math.floor(Math.random() * this.sum);
  let start = 0;
  let end = this.weights.length - 1;
  while (start <= end) {
    let mid = Math.floor((start + end) / 2);
    if (index < this.weights[mid]) {
      end = mid - 1;
    } else {
      start = mid + 1;
    }
  }
  return start;
};
/**
 * Your Solution object will be instantiated and called as such:
 * var obj = new Solution(w)
 * var param_1 = obj.pickIndex()
 */
這題首先可以算出整個 w 陣列的所有值的總和,以及建立一個新陣列 weights,記錄當前遍歷過權重的總和。例如 w = [2, 1, 5, 4] 時,sum = 12,weight = [2, 3, 8, 12]。
接著我們從 sum 裡面隨機抽一個數字,例如抽到 7,透過二分搜尋法查找後,它會在 weights 陣列的 3 & 8 之間,8 的 index 在 weight 內是 2,所以得出索引 2。
若 w 抽取的索引和機率轉化成比例長度,會變成以下的樣子:
w 抽取的 index:                 0    1        2            3
w 指定 index 被抽取的機率:    |     |  |              |           |
當前權重的累加總和:                 2  3              8           12
                            |  |  |  |  |  |  |  |  |  |  |  |  |
                            0  1  2  3  4  5  6  7  8  9  10 11 12
時間複雜度: init: O(n),pickIndex: O(log n)
空間複雜度: O(n)