Day3-位运算和树

165 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路。

位运算

需要明白的几个字符:<< >> & | ^
要转换自己的思想,用二进制看这几个字符
二进制在线运算

移位

<<:左移一位

  • 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的幂

image.png 常规解法,使用循环:

/**
 * @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-只出现一次的数字

image.png 常规解答方法,不是很符合题意,因为用了额外空间来存储

/**
 * @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-二叉树的最大深度

image.png

解题思路
原问题:计算以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-翻转二叉树

image.png

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