- 144. 二叉树的前序遍历
- 589. N 叉树的前序遍历
- 226. 翻转二叉树
- 102. 二叉树的层序遍历
- 107. 二叉树的层序遍历 II
- 103. 二叉树的锯齿形层序遍历
- 110. 平衡二叉树
- 112. 路径总和
- 105. 从前序与中序遍历序列构造二叉树
- 222. 完全二叉树的节点个数
144. 二叉树的前序遍历
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
提示: 树中节点数目在范围 [0, 100] 内 -100 <= Node.val <= 100
题意理解: 前序遍历二叉树 根 左 右 使用递归处理
- 边界处理 root为空返回[]
- res 为返回值
- 递归写法 根的值push进去,左子树迭代,右子树迭代
/**
* 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) {
if(!root) return [];
let res=[];
if(root) {
res.push(root.val);
}
if(root?.left) {
res=[...res,...preorderTraversal(root?.left)];
}
if(root?.right){
res=[...res,...preorderTraversal(root?.right)];
}
return res
};
589. N 叉树的前序遍历
给定一个 n 叉树的根节点 root ,返回 其节点值的 前序遍历 。 n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。
提示: 节点总数在范围 [0, 104]内 0 <= Node.val <= 104 n 叉树的高度小于或等于 1000
题意理解: 与上一提类似,知识把左右字数换成多子树 先遍历根 左 中1 中2 中3 ... 右
- 边界处理 root为空返回[]
- res 为返回值
- 递归写法 根的值push进去,迭代左 中1 中2 中3 ... 右,用for循环遍历
递归
/**
* // Definition for a Node.
* function Node(val, children) {
* this.val = val;
* this.children = children;
* };
*/
/**
* @param {Node|null} root
* @return {number[]}
*/
var preorder = function(root) {
if(!root) return [];
let res=[];
if(root) res.push(root.val);
if(root?.children){
for(const item of root?.children){
res=[...res,...preorder(item)]
}
}
return res
};
利用栈(先进后出)
- 初始化栈stack,将根节点推入栈中,res存储返回值
- 遍历栈,执行出栈,将出栈数据出入res,如果出栈数据有children,则从右往左遍历执行入栈操作,一次类推
- 返回res
/**
* // Definition for a Node.
* function Node(val, children) {
* this.val = val;
* this.children = children;
* };
*/
/**
* @param {Node|null} root
* @return {number[]}
*/
var preorder = function (root) {
if (!root) return [];
const res = [];
const stack = [];
stack.push(root)
while (stack.length) {
const currentNode = stack.pop();
res.push(currentNode.val)
for (let i = currentNode.children.length - 1; i >= 0; --i) {
stack.push(currentNode.children[i])
}
}
return res
};
迭代1
- 使用Map来存储每一层访问过的数据,从上到下,从左往右递推
/**
* // Definition for a Node.
* function Node(val, children) {
* this.val = val;
* this.children = children;
* };
*/
/**
* @param {Node|null} root
* @return {number[]}
*/
var preorder = function (root) {
if (!root) return [];
const res = [];
const stack = [];
const currentMap = new Map();
let currentNode = root;
while (stack.length || currentNode) {
while (currentNode) {
res.push(currentNode.val);
stack.push(currentNode)
currentMap.set(currentNode, 1)
currentNode = currentNode?.children?.[0] || null;
}
currentNode = stack[stack.length - 1]
while (currentNode?.children?.length && currentMap.get(currentNode) < currentNode?.children?.length) {
const currentIndex = currentMap.get(currentNode);
currentMap.set(currentNode, currentIndex + 1)
currentNode = currentNode?.children?.[currentIndex];
while (currentNode) {
res.push(currentNode.val);
stack.push(currentNode)
currentMap.set(currentNode, 1)
currentNode = currentNode?.children?.[0] || null;
}
}
stack.pop();
currentNode = null;
}
return res
};
迭代2
/**
* // Definition for a Node.
* function Node(val, children) {
* this.val = val;
* this.children = children;
* };
*/
/**
* @param {Node|null} root
* @return {number[]}
*/
var preorder = function (root) {
if (!root) return [];
const res = [];
const stack = [];
const currentMap = new Map();
let currentNode = root;
while (stack.length || currentNode) {
while (currentNode) {
res.push(currentNode.val);
stack.push(currentNode)
currentMap.set(currentNode, 1)
currentNode = currentNode?.children?.[0] || null;
}
currentNode = stack[stack.length - 1]
if (currentNode?.children?.length && currentMap.get(currentNode) < currentNode?.children?.length) {
const currentIndex = currentMap.get(currentNode);
currentMap.set(currentNode, currentIndex + 1)
currentNode = currentNode?.children?.[currentIndex];
}else{
stack.pop();
currentNode = null;
}
}
return res
};
226. 翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
提示: 树中节点数目范围在 [0, 100] 内 -100 <= Node.val <= 100
题意理解: 将二叉树左右翻转
- 递归翻转二叉树
/**
* 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 null;
if(root.left){
invertTree(root.left)
}
if(root.right){
invertTree(root.right)
}
[root.left,root.right]=[root.right,root.left]
return root
};
102. 二叉树的层序遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
提示: 树中节点数目在范围 [0, 2000] 内 -1000 <= Node.val <= 1000
题意理解: 按层遍历二叉树,及广度优先
- 使用栈的特性先进先出,一层一层遍历
/**
* 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 levelOrder = function(root) {
if(!root) return [];
const res=[];
let stack=[];
stack.push(root)
while(stack.length){
const cuurentLayer=[];
const currentLayerValue=[];
while(stack.length){
const value=stack.shift();
if(value.left) cuurentLayer.push(value.left)
if(value.right) cuurentLayer.push(value.right)
currentLayerValue.push(value.val)
}
stack=cuurentLayer
res.push(currentLayerValue)
}
return res;
};
107. 二叉树的层序遍历 II
给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
提示: 树中节点数目在范围 [0, 2000] 内 -1000 <= Node.val <= 1000
题意理解: 与上题原理相同(102. 二叉树的层序遍历)
- 最后将结果翻转一下就行
/**
* 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) {
if(!root) return [];
const res=[];
let stack=[];
stack.push(root);
while(stack.length){
const currentLayer=[];
const currentLayerValue=[];
while(stack.length){
const currentNode = stack.shift();
currentLayerValue.push(currentNode.val)
if(currentNode.left) currentLayer.push(currentNode.left);
if(currentNode.right) currentLayer.push(currentNode.right);
}
stack=currentLayer;
res.push(currentLayerValue)
}
return res.reverse();
};
103. 二叉树的锯齿形层序遍历
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
提示: 树中节点数目在范围 [0, 2000] 内 -100 <= Node.val <= 100
题意理解: 与题(二叉树的层序遍历)原理相同;
- 每层加个开关,如果是奇数则不处理,偶数则翻转当前层的结果
/**
* 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) {
if(!root) return [];
const res=[];
let stack=[];
stack.push(root);
let isSingle=true;
while(stack.length){
const currentLayer=[];
const currentLayerValue=[];
while(stack.length){
const currentNode = stack.shift();
currentLayerValue.push(currentNode.val)
if(currentNode.left) currentLayer.push(currentNode.left);
if(currentNode.right) currentLayer.push(currentNode.right);
}
stack=currentLayer;
const value = isSingle?currentLayerValue:currentLayerValue.reverse();
res.push(value)
isSingle=!isSingle
}
return res;
};
110. 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
提示: 树中的节点数在范围 [0, 5000] 内 -104 <= Node.val <= 104
题意理解: 判断一颗二叉树是否是平衡二叉树
- 递归计算二叉树的左右子树的高度
- 如果左右子树相差大于1则返回false否则返回true
/**
* 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) {
if(!root) return true;
function height(root){
if(!root) return 0;
const leftHeight=height(root.left);
const rightHeight=height(root.right);
if(leftHeight<0 || rightHeight<0 || Math.abs(leftHeight-rightHeight)>1){
return -1
}else{
return Math.max(leftHeight,rightHeight)+1;
}
}
return height(root)>=0
};
112. 路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。 叶子节点 是指没有子节点的节点。
提示: 树中节点的数目在范围 [0, 5000] 内 -1000 <= Node.val <= 1000 -1000 <= targetSum <= 1000
题意理解: 判断给定的树是否存在一条路径,是否存在从根节点到叶子节点的路径之和目标值相同的路径
- 递归
/**
* 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) return false;
if (!root.left && !root.right) {
return targetSum === root.val;
}
return hasPathSum(root.left,targetSum-root.val) || hasPathSum(root.right,targetSum-root.val);
};
105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
提示: 1 <= preorder.length <= 3000 inorder.length == preorder.length -3000 <= preorder[i], inorder[i] <= 3000 preorder 和 inorder 均 无重复 元素 inorder 均出现在 preorder preorder 保证 为二叉树的前序遍历序列 inorder 保证 为二叉树的中序遍历序列
题意理解: 先序遍历: 根 左 右 中序遍历: 左 根 右
- 可以确定节点值为preorder[0],借助栈来进行数据操作
- startIndex表示中序遍历已确定的数的下标
- 遍历preorder,i=1开始stack[stack.length - 1].val !== inorder[startIndex]表示是当前节点的左节点,否则为有节点
- 右节点需要执行出栈操作,确定中序遍历的为左节点的位置用while循环判断
/**
* 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) {
const root = new TreeNode(preorder[0])
const stack = [];
stack.push(root);
let startIndex = 0;
for (let i = 1; i < preorder.length; i++) {
let currentNode = stack[stack.length - 1]
if (stack[stack.length - 1].val !== inorder[startIndex]) {
currentNode.left = new TreeNode(preorder[i])
stack.push(currentNode.left)
} else {
while (stack.length && stack[stack.length - 1].val === inorder[startIndex]) {
currentNode = stack.pop()
startIndex++;
}
currentNode.right = new TreeNode(preorder[i])
stack.push(currentNode.right)
}
}
return root;
};
222. 完全二叉树的节点个数
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
提示: 树中节点的数目范围是[0, 5 * 104] 0 <= Node.val <= 5 * 104 题目数据保证输入的树是 完全二叉树
题意理解: 统计完全二叉树中节点个数
- 递归可使用所有二叉树
/**
* 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) return 0;
const l = countNodes(root.left);
const r = countNodes(root.right);
return 1 + l + r;
};
利用完全二叉树的特性 递归的另一种写法
/**
* 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) return 0;
let leftLevel = 0;
let rightLevel = 0;
let currentNode = root.left;
while (currentNode) {
leftLevel++;
currentNode = currentNode.left;
}
currentNode = root.right
while (currentNode) {
rightLevel++;
currentNode = currentNode.left;
}
if(leftLevel<=rightLevel) return countNodes(root.right)+(1<<leftLevel);
else return countNodes(root.left)+(1<<rightLevel)
};
- 左子树节点深度大于右节点深度,则左边不完全
- 否则右边不完全
- 递归计算
/**
* 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)
* }
*/
function height(root) {
let currentNode = root;
let level = 0;
while (currentNode) {
level++;
currentNode = currentNode.left;
}
return level;
}
/**
* @param {TreeNode} root
* @return {number}
*/
var countNodes = function (root) {
if (!root) return 0;
const l = height(root.left);
const r = height(root.right);
if (l > r) return countNodes(root.left)+(1<<r);
else return countNodes(root.right)+(1<<l)
};