转载链接
位运算的一些小技巧
判断一个整数 x 的奇偶性: x & 1 = 1 (奇数) , x & 1 = 0 (偶数)
求一个浮点数 x 的整数部分: ~~x ,对于正数相当于 floor(x) 对于负数相当于 ceil(-x)
计算 2 ^ n : 1 << n 相当于 pow(2, n)
计算一个数 x 除以 2 的 n 倍: x >> n 相当于 ~~(x / pow(2, n))
判断一个数 x 是 2 的整数幂(即 x = 2 ^ n ): x & (x - 1) = 0
※注意※:上面的位运算只对32位带符号的整数有效,如果使用的话,一定要注意数!据!范!围!
记住这些技巧的作用:
提升运行速度 ❌
提升逼格 ✅
举一个实用的例子,快速幂(原理自行google)
// 计算x^n n为整数
function qPow(x, n) {
let result = 1;
while (n) {
if (n & 1) result = x; // 同 if(n%2)
x = x x;
n >>= 1; // 同 n=floor(n/2)
}
return result;
}
在 VS Code 中刷 LeetCode
前面说的那些模板,难道每一次打开新的一道题都要复制一遍么?当然不用啦。
首先配置代码片段 选择 Code -> Preferences -> User Snippets ,然后选择 JavaScript
在文件中插入代码
复制代码{"leetcode template": {"prefix": "@lc","body": ["const _max = Math.max.bind(Math);","const _min = Math.min.bind(Math);","const _pow = Math.pow.bind(Math);","const _floor = Math.floor.bind(Math);","const _round = Math.round.bind(Math);","const _ceil = Math.ceil.bind(Math);","const log = console.log.bind(console);","// const log = _ => {}","/**************** 链表 ****************/","/**"," * 链表节点"," * @param {*} val"," * @param {ListNode} next"," */","function ListNode(val, next = null) {"," this.val = val;"," this.next = next;","}","/**"," * 将一个数组转为链表"," * @param {array} array"," * @return {ListNode}"," */","const getListFromArray = (array) => {"," let dummy = new ListNode()"," let pre = dummy;"," array.forEach(x => pre = pre.next = new ListNode(x));"," return dummy.next;","}","/**"," * 将一个链表转为数组"," * @param {ListNode} list"," * @return {array}"," */","const getArrayFromList = (list) => {"," let a = [];"," while (list) {"," a.push(list.val);"," list = list.next;"," }"," return a;","}","/**"," * 打印一个链表"," * @param {ListNode} list "," */","const logList = (list) => {"," let str = 'list: ';"," while (list) {"," str += list.val + '->';"," list = list.next;"," }"," str += 'end';"," log(str);","}","/**************** 矩阵(二维数组) ****************/","/**"," * 初始化一个二维数组"," * @param {number} r 行数"," * @param {number} c 列数"," * @param {*} init 初始值"," */","const initMatrix = (r, c, init = 0) => new Array(r).fill().map(_ => new Array(c).fill(init));","/**"," * 获取一个二维数组的行数和列数"," * @param {any[][]} matrix"," * @return [row, col]"," */","const getMatrixRowAndCol = (matrix) => matrix.length === 0 ? [0, 0] : [matrix.length, matrix[0].length];","/**"," * 遍历一个二维数组"," * @param {any[][]} matrix "," * @param {Function} func "," */","const matrixFor = (matrix, func) => {"," matrix.forEach((row, i) => {"," row.forEach((item, j) => {"," func(item, i, j, row, matrix);"," });"," })","}","/**"," * 获取矩阵第index个元素 从0开始"," * @param {any[][]} matrix "," * @param {number} index "," */","function getMatrix(matrix, index) {"," let col = matrix[0].length;"," let i = ~~(index / col);"," let j = index - i * col;"," return matrix[i][j];","}","/**"," * 设置矩阵第index个元素 从0开始"," * @param {any[][]} matrix "," * @param {number} index "," */","function setMatrix(matrix, index, value) {"," let col = matrix[0].length;"," let i = ~~(index / col);"," let j = index - i * col;"," return matrix[i][j] = value;","}","/**************** 二叉树 ****************/","/**"," * 二叉树节点"," * @param {*} val"," * @param {TreeNode} left"," * @param {TreeNode} right"," */","function TreeNode(val, left = null, right = null) {"," this.val = val;"," this.left = left;"," this.right = right;","}","/**"," * 通过一个层次遍历的数组生成一棵二叉树"," * @param {any[]} array"," * @return {TreeNode}"," */","function getTreeFromLayerOrderArray(array) {"," let n = array.length;"," if (!n) return null;"," let index = 0;"," let root = new TreeNode(array[index++]);"," let queue = [root];"," while(index < n) {"," let top = queue.shift();"," let v = array[index++];"," top.left = v == null ? null : new TreeNode(v);"," if (index < n) {"," let v = array[index++];"," top.right = v == null ? null : new TreeNode(v);"," }"," if (top.left) queue.push(top.left);"," if (top.right) queue.push(top.right);"," }"," return root;","}","/**"," * 层序遍历一棵二叉树 生成一个数组"," * @param {TreeNode} root "," * @return {any[]}"," */","function getLayerOrderArrayFromTree(root) {"," let res = [];"," let que = [root];"," while (que.length) {"," let len = que.length;"," for (let i = 0; i < len; i++) {"," let cur = que.shift();"," if (cur) {"," res.push(cur.val);"," que.push(cur.left, cur.right);"," } else {"," res.push(null);"," }"," }"," }"," while (res.length > 1 && res[res.length - 1] == null) res.pop(); // 删掉结尾的 null"," return res;","}","/**************** 二分查找 ****************/","/**"," * 寻找>=target的最小下标"," * @param {number[]} nums"," * @param {number} target"," * @return {number}"," */","function lower_bound(nums, target) {"," let first = 0;"," let len = nums.length;",""," while (len > 0) {"," let half = len >> 1;"," let middle = first + half;"," if (nums[middle] < target) {"," first = middle + 1;"," len = len - half - 1;"," } else {"," len = half;"," }"," }"," return first;","}","","/**"," * 寻找>target的最小下标"," * @param {number[]} nums"," * @param {number} target"," * @return {number}"," */","function upper_bound(nums, target) {"," let first = 0;"," let len = nums.length;",""," while (len > 0) {"," let half = len >> 1;"," let middle = first + half;"," if (nums[middle] > target) {"," len = half;"," } else {"," first = middle + 1;"," len = len - half - 1;"," }"," }"," return first;","}","$1"],"description": "LeetCode常用代码模板"}}
具体常用代码:
const _max = Math.max.bind(Math);const _min = Math.min.bind(Math);const _pow = Math.pow.bind(Math); //次方const _floor = Math.floor.bind(Math); //向下取整const _round = Math.round.bind(Math); //四舍五入const _ceil = Math.ceil.bind(Math); //向上取整const log = console.log.bind(console);// const log = _ => {}//注:第八行将log赋值给空函数是为了注释掉后面所有的log/**************** 链表 ****************//*** 链表节点* @param {*} val* @param {ListNode} next*/function ListNode(val, next = null) {this.val = val;this.next = next;}/*** 将一个数组转为链表* @param {array} array* @return {ListNode}*/const getListFromArray = (array) => {let dummy = new ListNode()let pre = dummy;array.forEach(x => pre = pre.next = new ListNode(x));return dummy.next;}/*** 将一个链表转为数组* @param {ListNode} list* @return {array}*/const getArrayFromList = (list) => {let a = [];while (list) {a.push(list.val);list = list.next;}return a;}/*** 打印一个链表* @param {ListNode} list*/const logList = (list) => {let str = 'list: ';while (list) {str += list.val + '->';list = list.next;}str += 'end';log(str);}/**************** 矩阵(二维数组) ****************//*** 初始化一个二维数组* @param {number} r 行数* @param {number} c 列数* @param {*} init 初始值*/const initMatrix = (r, c, init = 0) => new Array(r).fill().map(_ => new Array(c).fill(init));/*** 获取一个二维数组的行数和列数* @param {any[][]} matrix* @return [row, col]*/const getMatrixRowAndCol = (matrix) => matrix.length === 0 ? [0, 0] : [matrix.length, matrix[0].length];/*** 遍历一个二维数组* @param {any[][]} matrix* @param {Function} func*/const matrixFor = (matrix, func) => {matrix.forEach((row, i) => {row.forEach((item, j) => {func(item, i, j, row, matrix);});})}/*** 获取矩阵第index个元素 从0开始* @param {any[][]} matrix* @param {number} index*/function getMatrix(matrix, index) {let col = matrix[0].length;let i = ~~(index / col);let j = index - i * col;return matrix[i][j];}/*** 设置矩阵第index个元素 从0开始* @param {any[][]} matrix* @param {number} index*/function setMatrix(matrix, index, value) {let col = matrix[0].length;let i = ~~(index / col);let j = index - i * col;return matrix[i][j] = value;}/**************** 二叉树 ****************//*** 二叉树节点* @param {*} val* @param {TreeNode} left* @param {TreeNode} right*/function TreeNode(val, left = null, right = null) {this.val = val;this.left = left;this.right = right;}/*** 通过一个层次遍历的数组生成一棵二叉树* @param {any[]} array* @return {TreeNode}*/function getTreeFromLayerOrderArray(array) {let n = array.length;if (!n) return null;let index = 0;let root = new TreeNode(array[index++]);let queue = [root];while(index < n) {let top = queue.shift();let v = array[index++];top.left = v == null ? null : new TreeNode(v);if (index < n) {let v = array[index++];top.right = v == null ? null : new TreeNode(v);}if (top.left) queue.push(top.left);if (top.right) queue.push(top.right);}return root;}/*** 层序遍历一棵二叉树 生成一个数组* @param {TreeNode} root* @return {any[]}*/function getLayerOrderArrayFromTree(root) {let res = [];let que = [root];while (que.length) {let len = que.length;for (let i = 0; i < len; i++) {let cur = que.shift();if (cur) {res.push(cur.val);que.push(cur.left, cur.right);} else {res.push(null);}}}while (res.length > 1 && res[res.length - 1] == null) res.pop(); // 删掉结尾的 nullreturn res;}/**************** 二分查找 ****************//*** 寻找>=target的最小下标* @param {number[]} nums* @param {number} target* @return {number}*/function lower_bound(nums, target) {let first = 0;let len = nums.length;while (len > 0) {let half = len >> 1;let middle = first + half;if (nums[middle] < target) {first = middle + 1;len = len - half - 1;} else {len = half;}}return first;}/*** 寻找>target的最小下标* @param {number[]} nums* @param {number} target* @return {number}*/function upper_bound(nums, target) {let first = 0;let len = nums.length;while (len > 0) {let half = len >> 1;let middle = first + half;if (nums[middle] > target) {len = half;} else {first = middle + 1;len = len - half - 1;}}return first;}
