本文已参与[新人创作礼]活动,一起开启掘金创作之路。
位运算
需要明白的几个字符:<< >> & | ^
要转换自己的思想,用二进制看这几个字符
二进制在线运算
移位
<<:左移一位
- 1: 0001
- 1<<2: 0010
- 29: 0001 1101
- 29<<4: 0001 1101 0000
分析:二进制左移几位,就在后面加几个0。
0001 1101 0000,后面的4个0,就是左移4位加上的。
前面的0001中的前三个0,是占位用,没什么意义,因为一般二进制是四位展示。
用29举例 29<<3
0001 1101
0000 1110 1000
右移一位:>>
- 1>>1: 0000
- 29>>2: 0000 0111 分析:二进制右移几位,就去掉后面几位,前面用0补位。
用15举例 15>>2
1111
0011
运算规则
- &:与运算,有0就为0
- |:或运算,有1就为1
- ^:异或运算,相同为false,不同为true
16&15(十进制看没什么意义,要转成二进制看)
00010000
00001111
&后 00000000
------------------------------------
12|8
1100
1000
|后 1100
------------------------------------
9^21
00001001
00010101
^后 00011100
了解以上概念后,就可以开始刷题了
力扣231-2的幂
常规解法,使用循环:
/**
* @param {number} n
* @return {boolean}
*/
var isPowerOfTwo = function(n) {
let x = 1
while (x < n) {
x = x * 2
}
return x === n
};
与运算方法: 2的幂次方的值,都是1后面跟一串0,而2^n-1则是头位为0,其他位都是1,这样与的时候,有0就为0,那么(n&(n-1))===0的话,就是题解。
/**
* @param {number} n
* @return {boolean}
*/
var isPowerOfTwo = function(n) {
return n > 0 && (n&(n-1))===0
};
力扣136-只出现一次的数字
常规解答方法,不是很符合题意,因为用了额外空间来存储
/**
* @param {number[]} nums
* @return {number}
*/
// 写完发现,这是一个链表和数组怎么应用的很好的demo
var singleNumber = function(nums) {
let tmp = new Set();
nums.forEach(item => {
if (tmp.has(item)) {
tmp.delete(item)
} else {
tmp.add(item)
}
})
return tmp.values().next().value
};
异或方式:
两个相同的数,异或后一定是false,所以result就是单个的那个
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
let result = 0;
nums.forEach(item => {
// result = result ^ item
result ^= item;
})
return result
};
位运算在前端的应用
经常用于授权和判断,常见于vue/react源码
const a = 1
const b = 1 << 1
const c = 1 << 2
const d = 1 << 3
// 授权 |
let type = a | b | c
// 判断 &
console.log('type a', !!(type & a)) // true
console.log('type b', !!(type & b)) // true
console.log('type c', !!(type & c)) // true
console.log('type d', !!(type & d)) // false
// 删除授权 ^
type = type ^ c
console.log('type c', !!(type & c)) // false
树
树可以看作是链表的一种变体。
二叉树的结构:
function TreeNode(val, left, right) {
this.val = val
this.left = null
this.right = null
}
链表
function Node(val, next) {
this.val = val
this.next = null
}
力扣104-二叉树的最大深度
解题思路
原问题:计算以3为节点的二叉树深度
子问题1:计算以9为节点的二叉树深度
子问题2:计算以20为节点的二叉树深度
取自问题1和2中最大的值
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var maxDepth = function(root) {
if (root == null) {
// 注意,传入的是节点,输出的是深度
return 0
}
return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1
};
力扣226-翻转二叉树
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var maxDepth = function(root) {
if (root == null) {
return 0
}
return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1
};