理解二叉树?从刷题开始

一. 什么是二叉树

二叉树是指满足以下要求的树:

  • 它可以没有根结点,作为一棵空树存在
  • 如果它不是空树,那么必须由根结点、左子树和右子树组成,且左右子树都是二叉树

注意,二叉树不能被简单定义为每个结点的度都是2的树。普通的树并不会区分左子树和右子树,但在二叉树中,左右子树的位置是严格约定、不能交换的。对应到图上来看,也就意味着 B 和 C、D 和 E、F 和 G 是不能互换的。

二. 二叉树的递归遍历

先序遍历

根结点 -> 左子树 -> 右子树

js 复制代码
 // 所有遍历函数的入参都是树的根结点对象
 function preorder(root) {
     // 递归边界,root 为空
     if(!root) {
         return 
     }
      
     // 输出当前遍历的结点值
     console.log('当前遍历的结点值是:', root.val)  
     // 递归遍历左子树 
     preorder(root.left)  
     // 递归遍历右子树  
     preorder(root.right)
 }

中序遍历

左子树 -> 根结点 -> 右子树

js 复制代码
 // 所有遍历函数的入参都是树的根结点对象
 function inorder(root) {
     // 递归边界,root 为空
     if(!root) {
         return 
     }
      
     // 递归遍历左子树 
     inorder(root.left)  
     // 输出当前遍历的结点值
     console.log('当前遍历的结点值是:', root.val)  
     // 递归遍历右子树  
     inorder(root.right)
 }

后序遍历

左子树 -> 右子树 -> 根结点

scss 复制代码
 function postorder(root) {
     // 递归边界,root 为空
     if(!root) {
         return 
     }
      
     // 递归遍历左子树 
     postorder(root.left)  
     // 递归遍历右子树  
     postorder(root.right)
     // 输出当前遍历的结点值
     console.log('当前遍历的结点值是:', root.val)  
 }

三. 题目

144. 二叉树的前序遍历

1. 题目

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

ini 复制代码
 输入:root = [1,null,2,3]
 输出:[1,2,3]

示例 2:

ini 复制代码
 输入:root = []
 输出:[]

示例 3:

ini 复制代码
 输入:root = [1]
 输出:[1]

示例 4:

ini 复制代码
 输入:root = [1,2]
 输出:[1,2]

示例 5:

ini 复制代码
 输入:root = [1,null,2]
 输出:[1,2]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

2. 解答

js 复制代码
 /**
  * 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 preorderTraversal = function(root) {
     const res = []
     if(!root){
         return res
     }
 ​
     const stack = []
     stack.push(root)
 ​
     while(stack.length){
         const cur = stack.pop()
         res.push(cur.val)
 ​
         if(cur.right){
             stack.push(cur.right)
         }
 ​
         if(cur.left){
             stack.push(cur.left)
         }
     }
     return res
 };
js 复制代码
 /**
  * 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 preorder = function(root, res) {
     if(root === null) return
     res.push(root.val)
     preorder(root.left, res)
     preorder(root.right, res)
     return
 }
 var preorderTraversal = function(root) {
     let res = []
     preorder(root, res)
     return res
 };

589. N 叉树的前序遍历

1. 题目

给定一个 n 叉树的根节点 root ,返回 其节点值的 前序遍历 。

n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

示例 1:

ini 复制代码
 输入:root = [1,null,3,2,4,null,5,6]
 输出:[1,3,5,6,2,4]

示例 2:

csharp 复制代码
 输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
 输出:[1,2,3,6,7,11,14,4,8,12,5,9,13,10]

提示:

  • 节点总数在范围 [0, 104]内
  • 0 <= Node.val <= 104
  • n 叉树的高度小于或等于 1000

2. 解答

js 复制代码
 /**
  * // Definition for a Node.
  * function Node(val, children) {
  *    this.val = val;
  *    this.children = children;
  * };
  */
 ​
 /**
  * @param {Node|null} root
  * @return {number[]}
  */
 ​
 var _preorder = function(root, res) {
     if(root === null) return
     res.push(root.val)
     for(let i of root.children) {
         _preorder(i, res)
     }
     return
 }
 ​
 var preorder = function(root) {
     let res = []
     _preorder(root, res)
     return res
 };

226. 翻转二叉树

1. 题目

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

ini 复制代码
 输入:root = [4,2,7,1,3,6,9]
 输出:[4,7,2,9,6,3,1]

示例 2:

ini 复制代码
 输入:root = [2,1,3]
 输出:[2,3,1]
 示例 3:
 ​
 输入:root = []
 输出:[]

提示:

  • 树中节点数目范围在 [0, 100] 内
  • -100 <= Node.val <= 100

2. 解答

js 复制代码
 /**
  * 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 {TreeNode}
  */
 var invertTree = function(root) {
     if(!root) return root
     let left = invertTree(root.left)
     let right = invertTree(root.right)
 ​
     root.left = right
     root.right = left
     return root
 };

剑指 Offer 32 - II. 从上到下打印二叉树 II

1. 题目

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例如:

给定二叉树:[3,9,20,null,null,15,7],

markdown 复制代码
    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

csharp 复制代码
[
  [3],
  [9,20],
  [15,7]
]

提示:

  • 节点总数 <= 1000

2. 解答

js 复制代码
 /**
  * Definition for a binary tree node.
  * function TreeNode(val) {
  *     this.val = val;
  *     this.left = this.right = null;
  * }
  */
 /**
  * @param {TreeNode} root
  * @return {number[][]}
  */
 var levelOrder = function(root) {
     let res = []
     getResult(root, 0, res)
     return res
 };
 ​
 var getResult = function(root, k, res) {
     if(root === null) return
 ​
     if(k === res.length) res.push([])
     res[k].push(root.val)
 ​
     getResult(root.left, k + 1, res)
     getResult(root.right, k + 1, res)
 ​
     return
 }

107. 二叉树的层序遍历 II

1. 题目

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

示例 1:

ini 复制代码
输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

示例 2:

ini 复制代码
输入:root = [1]
输出:[[1]]
示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000] 内
  • -1000 <= Node.val <= 1000

2. 解答

js 复制代码
 /**
  * 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 levelOrderBottom = function(root) {
     let res = []
     let k = 0
     lv(root, k, res)
 ​
     // 交换位置
     for(let i = 0, j = res.length - 1; i < j; i++, j--) {
         [res[i], res[j]] = [res[j], res[i]]
     }
     return res
 };
 ​
 var lv = function(root, k, res) {
     if(root === null) return
 ​
     if(k === res.length) res.push([])
     res[k].push(root.val)
 ​
     lv(root.left, k + 1, res)
     lv(root.right, k + 1, res)
 ​
     return
 }

103. 二叉树的锯齿形层序遍历

1. 题目

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

示例 1:

ini 复制代码
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]

示例 2:

ini 复制代码
输入:root = [1]
输出:[[1]]
示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000] 内
  • -100 <= Node.val <= 100

2. 解答

js 复制代码
/**
 * 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 zigzagLevelOrder = function(root) {
    let res = []
    let k = 0
    getResult(root, k, res)

    for(let i = 1; i < res.length; i+=2) {
        rever(res[i])
    }

    return res
};

var rever = function(ary) {
    for(let i = 0, j = ary.length - 1; i < j; i++,j--) {
        [ary[i], ary[j]] = [ary[j], ary[i]]
    }
    return ary
}

var getResult = function(root, k, res) {
    if(root === null) return

    if(k === res.length) res.push([])
    res[k].push(root.val)
    getResult(root.left, k + 1, res)
    getResult(root.right, k + 1, res)

    return
}
js 复制代码
 /**
  * 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 zigzagLevelOrder = function(root) {
     let res = []
     let k = 0
     getResult(root, k, res)
 ​
     return res
 };
 ​
 var getResult = function(root, k, res) {
     if(root === null) return
 ​
     if(k === res.length) res.push([])
     k%2 ? res[k].unshift(root.val) : res[k].push(root.val)
     getResult(root.left, k + 1, res)
     getResult(root.right, k + 1, res)
 ​
     return
 }

110. 平衡二叉树

1. 题目

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:

csharp 复制代码
 输入:root = [3,9,20,null,null,15,7]
 输出:true

示例 2:

csharp 复制代码
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false

示例 3:

ini 复制代码
输入:root = []
输出:true

提示:

  • 树中的节点数在范围 [0, 5000] 内
  • -104 <= Node.val <= 104

2. 解答

js 复制代码
 /**
  * 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 {boolean}
  */
 var isBalanced = function(root) {
     return getHeight(root) >= 0
 };
 var getHeight = function(root){
     if(root===null) return 0
     let l = getHeight(root.left)
     let r = getHeight(root.right)
 ​
     if(l < 0 || r < 0) return -2
     if(Math.abs(l - r) > 1) return -2 
     return Math.max(l, r) + 1
 }
 /**
  * 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 {boolean}
  */
 var isBalanced = function(root) {
     let flag = true
 ​
     function dfs(root){
         if(!root || !flag){
             return 0
         }
 ​
         let left = dfs(root.left)
         let right = dfs(root.right)
 ​
         if(Math.abs(left - right) > 1){
             flag = false
             return 0
         }
 ​
         return Math.max(left, right) + 1
     }
 ​
     dfs(root)
     return flag
 };

112. 路径总和

1. 题目

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

示例 1:

csharp 复制代码
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

ini 复制代码
输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

ini 复制代码
输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

提示:

  • 树中节点的数目在范围 [0, 5000] 内
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

2. 解答

js 复制代码
/**
 * 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
 * @param {number} targetSum
 * @return {boolean}
 */
var hasPathSum = function(root, targetSum) {
    if(root === null) return false
    if(root.left === null && root.right === null) return root.val === targetSum
    if(root.left && hasPathSum(root.left, targetSum - root.val)) return true
    if(root.right && hasPathSum(root.right, targetSum - root.val)) return true
    return false
};
js 复制代码
/**
 * 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
 * @param {number} targetSum
 * @return {boolean}
 */
var hasPathSum = function(root, targetSum) {
    if(root === null) return false
    if(!root.left && !root.right) return targetSum === root.val

    targetSum -= root.val
    return hasPathSum(root.left, targetSum) || hasPathSum(root.right, targetSum)
};

105. 从前序与中序遍历序列构造二叉树

1. 题目

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

ini 复制代码
 输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
 输出: [3,9,20,null,null,15,7]

示例 2:

ini 复制代码
 输入: preorder = [-1], inorder = [-1]
 输出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder 和 inorder 均 无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

2. 解答

js 复制代码
 /**
  * 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 {number[]} preorder
  * @param {number[]} inorder
  * @return {TreeNode}
  */
 var buildTree = function(preorder, inorder) {
     if(preorder.length === 0) return null
     let head = preorder[0]
     let index = 0
     while(inorder[index] !== head) ++index
 ​
     let l_pre = [], l_in = [], r_pre = [], r_in = [];
 ​
     for(let i = 0; i < index; i++) {
         l_pre.push(preorder[i+1])
         l_in.push(inorder[i])
     }
 ​
     for(let j = index+1; j < preorder.length; j++) {
         r_pre.push(preorder[j])
         r_in.push(inorder[j])
     }
 ​
 ​
     let root = new TreeNode(head)
     root.left = buildTree(l_pre, l_in)
     root.right = buildTree(r_pre, r_in)
     return root
 ​
 };

106. 从中序与后序遍历序列构造二叉

1. 题目

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

示例 1:

css 复制代码
 输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
 输出:[3,9,20,null,null,15,7]

示例 2:

css 复制代码
 输入:inorder = [-1], postorder = [-1]
 输出:[-1]

提示:

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorder 和 postorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder 中
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历

2. 解答

js 复制代码
 /**
  * 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 {number[]} inorder
  * @param {number[]} postorder
  * @return {TreeNode}
  */
 var buildTree = function(inorder, postorder) {
     if(postorder.length === 0) return null
     let head = postorder[postorder.length - 1]
 ​
     let index= 0
     while(inorder[index] !== head) ++index
 ​
     let l_in = [], l_pos = [], r_in = [],r_pos = [];
 ​
     for(let i = 0; i < index; i++) {
         l_in.push(inorder[i])
         l_pos.push(postorder[i])
     }
 ​
     for(let j = index; j < postorder.length - 1; j++) {
         r_in.push(inorder[j+1])
         r_pos.push(postorder[j])
     }
 ​
     let head_node = new TreeNode(head)
     head_node.left = buildTree(l_in, l_pos)
     head_node.right = buildTree(r_in, r_pos)
     return head_node
 };

222. 完全二叉树的节点个数

1. 题目

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例 1:

ini 复制代码
 输入:root = [1,2,3,4,5,6]
 输出:6

示例 2:

ini 复制代码
 输入:root = []
 输出:0

示例 3:

ini 复制代码
 输入:root = [1]
 输出:1

提示:

  • 树中节点的数目范围是[0, 5 * 104]
  • 0 <= Node.val <= 5 * 104
  • 题目数据保证输入的树是 完全二叉树

2. 解答

js 复制代码
 /**
  * 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 countNodes = function(root) {
     if(root === null) return 0
     return countNodes(root.left) + countNodes(root.right) + 1
 };

剑指 Offer 54. 二叉搜索树的第k大节点

1. 题目

给定一棵二叉搜索树,请找出其中第 k 大的节点的值。

示例 1:

ini 复制代码
 输入: root = [3,1,4,null,2], k = 1
 ​
    3
   / \
  1   4
   \
    2
 ​
 输出: 4

示例 2:

csharp 复制代码
 输入: root = [5,3,6,2,4,null,null,1], k = 3
 ​
 ​
        5
       / \
      3   6
     / \
    2   4
   /
  1
 ​
 输出: 4

限制:

  • 1 ≤ k ≤ 二叉搜索树元素个数

2. 解答

二叉搜索树:右节点大于根节点,左节点小于根节点

js 复制代码
 /**
  * Definition for a binary tree node.
  * function TreeNode(val) {
  *     this.val = val;
  *     this.left = this.right = null;
  * }
  */
 /**
  * @param {TreeNode} root
  * @param {number} k
  * @return {number}
  */
 ​
 var getLen = function(root) {
     if(root === null) return 0
     return getLen(root.left) + getLen(root.right) + 1
 }
 var kthLargest = function(root, k) {
     let r_len = getLen(root.right)
     if(k <= r_len) return kthLargest(root.right, k)
     if(k === r_len+1) return root.val
     return kthLargest(root.left, k - r_len - 1)
 };
 // 中序遍历取第k个
 /**
  * Definition for a binary tree node.
  * function TreeNode(val) {
  *     this.val = val;
  *     this.left = this.right = null;
  * }
  */
 /**
  * @param {TreeNode} root
  * @param {number} k
  * @return {number}
  */
 ​
 var in_order = function(root, ans) {
     if(root === null) return
     in_order(root.left, ans)
     ans.push(root.val)
     in_order(root.right, ans)
     return
 }
 var kthLargest = function(root, k) {
     let ans = []
     in_order(root, ans)
     return ans[ans.length - k]
 };

剑指 Offer 26. 树的子结构

1. 题目

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:

给定的树 A:

css 复制代码
    3
     / \
    4   5
   / \
  1   2
 ​
 给定的树 B:
 ​
    4 
   /
  1

返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

示例 1:

css 复制代码
 输入:A = [1,2,3], B = [3,1]
 输出:false

示例 2:

css 复制代码
 输入:A = [3,4,5,1,2], B = [4,1]
 输出:true

限制:

  • 0 <= 节点个数 <= 10000

2. 解答

js 复制代码
 /**
  * Definition for a binary tree node.
  * function TreeNode(val) {
  *     this.val = val;
  *     this.left = this.right = null;
  * }
  */
 /**
  * @param {TreeNode} A
  * @param {TreeNode} B
  * @return {boolean}
  */
 var isSubStructure = function(A, B) {
     if(B===null) return false
     if(A===null) return false
 ​
     if(A.val === B.val && is_match(A, B)) return true
     return isSubStructure(A.left, B)|| isSubStructure(A.right, B)
 };
 ​
 // 比较每一层
 var is_match = function(a, b) {
     if(b === null) return true
     if(a === null) return false
 ​
     if(a.val !== b.val) return false
 ​
     return is_match(a.left, b.left) && is_match(a.right, b.right)
 }

662. 二叉树最大宽度

1. 题目

给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空。

每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。

示例 1:

csharp 复制代码
 输入: 
 ​
            1
          /   \
         3     2
        / \     \  
       5   3     9 
 ​
 输出: 4
 解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。

示例 2:

 输入: 
 ​
           1
          /  
         3    
        / \       
       5   3     
 ​
 输出: 2
 解释: 最大值出现在树的第 3 层,宽度为 2 (5,3)。

示例 3:

 输入: 
 ​
           1
          / \
         3   2 
        /        
       5      
 ​
 输出: 2
 解释: 最大值出现在树的第 2 层,宽度为 2 (3,2)。

示例 4:

csharp 复制代码
 输入: 
 ​
           1
          / \
         3   2
        /     \  
       5       9 
      /         \
     6           7
 输出: 8
 解释: 最大值出现在树的第 4 层,宽度为 8 (6,null,null,null,null,null,null,7)。

注意: 答案在32位有符号整数的表示范围内。

2. 解答

js 复制代码
 /**
  * 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}
  */
 ​
 ​
 // 给一整个树做编号,从左到右,从上到下开始
 // root 的编号为 1,那么root的左孩子编号就为2,右孩子编号为3
 // root.left的index = root的index*2  root.right的index = root的index*2+1
 // 然后定义一个变量max来记录快读的最大值,每层的序号减完后和max比较取大的值
 ​
 // width = Rindex - Lindex+1
 var widthOfBinaryTree = function(root) {
     if(root === null) return 0
     
     // 定义一个二维数组存储当千层的序号和存入的节点
     let que = [[0n, root]]
     let max = 1n
 ​
     while(que.length) {
         let width = (que[que.length - 1][0] - que[0][0]) + 1n;
         if(width > max) max = width
         let temp = []
 ​
         for(let [index, root] of que) {
             root.left && temp.push([index * 2n, root.left])
             root.right && temp.push([index * 2n + 1n, root.right])
         }
 ​
         que = temp
     }
     return Number(max)
 };
相关推荐
Martin -Tang12 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发12 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
秦jh_6 小时前
【Linux】多线程(概念,控制)
linux·运维·前端