6. 路径总和 === target
参数当前节点和累加和; 没有子节点了到达终点 判断target。哪个有子节点继续累加递归
var hasPathSum = function(root, targetSum) {
if(!root) return false;
let rt = false
recurse(root,root.val)
return rt
// 参数是某个节点 到某个节点的和; 注意边界
function recurse(root, sum) {
// 到达叶子结点 且总和相等
if(!root.left && !root.right && (targetSum == sum)){
rt = true
}
if(root.left){
recurse(root.left,sum+root.left.val)
}
if(root.right){
recurse(root.right,sum+root.right.val)
}
}
};
10. 求根节点到叶节点数字之和
var sumNumbers = function(root) {
// 参数:当前节点 当前节点前的和
function defs (node, sumNum){
// 如果当前节点没有 返回0
if(node === null){
return 0 // ****
}
// 当前节点有值 计算和
sumNum = 10*sumNum + node.val
// 是否为叶子节点 叶子节点直接返回和
if(node.left === null && node.right===null){
return sumNum
}
// 不是叶子节点继续调用这个方法
return defs(node.left, sumNum) + defs(node.right, sumNum)
}
return defs(root,0)
};
14. 二叉树的层序遍历
主要是queue 存储每一层的节点;循环的时候 先拿queue长度再循环;循环时候取值 push queue
var levelOrder = function(root) {
if(root === null) return []
let result = [];
// queue存储每一行 节点
let queue = [root]
while (queue.length){
// 一层长度
const leveSize = queue.length
// 一层的值
const tempArr = []
for(let i=0;i<leveSize;i++){
// 每次循环首部删除
const current = queue.shift()
tempArr.push(current.val)
current.left && queue.push(current.left)
current.right && queue.push(current.right)
}
result.push(tempArr)
}
return result
};
26.二叉树的最近公共祖先
var lowestCommonAncestor = function(root, p, q) {
// 没值 或者是目标值 直接返回根
if(!root || root === p || root === q){
return root
}
const left = lowestCommonAncestor(root.left, p, q)
const right = lowestCommonAncestor(root.right, p, q)
// 左子树右子树都有 root就是公共祖先
if(left&&right){
return root
}
// 只有一个有值 就是left或者right
return left?left:right
};
28. 两棵二叉搜索树中的所有元素
给你
root1
和root2
这两棵二叉搜索树。请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序根据二叉树的特点鲜中序获取到两棵树的值再 两棵树对比排序;排完后没有比较到的直接追加在最后
var getAllElements = function(root1, root2) {
let arr1=[],arr2=[], result=[]
// 中序遍历两棵树 再对比值
function getValue(root, arr){
if(!root)return;
root.left&&getValue(root.left, arr)
arr.push(root.val)
root.right&&getValue(root.right, arr)
}
getValue(root1,arr1)
getValue(root2,arr2)
while (arr1.length&&arr2.length){
if(arr1[0]<arr2[0]){
result.push(arr1.shift())
}else {
result.push(arr2.shift())
}
}
// 没比完的追加在后边
return [...result, ...arr1,...arr2]
};
49. 二叉搜索树中第K小的元素
// 二叉搜索树的一个关键特性是,对于任何给定的节点,其左子树的所有节点值都小于该节点,而其右子树的所有节点值都大于该节点。
var kthSmallest = function(root, k) {
let result =[]
function getVal(node){
if(node ==null || result.length>=k)return;
getVal(node.left)
result.push(node.val)
getVal(node.right)
}
getVal(root)
return result[k-1]
};
43. 二叉树的最大深度
var maxDepth = function(root) {
if(root === null){
return 0
}
// 每一层最大值 加 1
return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1
};
53. 对称二叉树
var isSymmetric = function(root) {
// 判断两个树是否是镜像对称的
function isMirror(left, right) {
// 都为null 到 两边的叶子节点 返回true
if (left === null && right === null) return true;
// 有一个为null 另一不为null 证明不是对称的
if (left === null || right === null) return false;
// 左子树的右子树 和 右子树的左子树比较 都相同的为对称二叉树
return (left.val === right.val) && isMirror(left.right, right.left) && isMirror(left.left, right.right);
}
// 判断一棵树是否是对称的
return isMirror(root, root);
};
92.二叉树的中序遍历
// 中序遍历 左中右
function inorderTraversal(root) {
const result = [];
function traverse(node) {
if (node === null) return;
traverse(node.left); // 遍历左子树
result.push(node.val); // 访问根节点
traverse(node.right); // 遍历右子树
}
traverse(root);
return result;
}
// 迭代法
function inorderTraversalIterative(root) {
const result = [];
const stack = [];
let current = root;
while (current !== null || stack.length > 0) {
// 先尽可能地访问左子树
while (current !== null) {
stack.push(current);
current = current.left;
}
// 当左子树访问完毕,回溯到最近的父节点
current = stack.pop();
result.push(current.val); // 访问根节点
// 转向右子树
current = current.right;
}
return result;
}
// 前序遍历 中左右
function preorderTraversal(root) {
const result = [];
function traverse(node) {
if (node === null) return;
result.push(node.val); // 访问根节点
traverse(node.left); // 遍历左子树
traverse(node.right); // 遍历右子树
}
traverse(root);
return result;
}
// 迭代法
function preorderTraversalIterative(root) {
if (root === null) return [];
const result = [];
const stack = [root];
while (stack.length > 0) {
const node = stack.pop();
result.push(node.val); // 访问根节点
// 先右后左入栈,保证左子树先处理
if (node.right !== null) stack.push(node.right);
if (node.left !== null) stack.push(node.left);
}
return result;
}
// 后续遍历 左右中
function postorderTraversal(root) {
const result = [];
function traverse(node) {
if (node === null) return;
traverse(node.left); // 遍历左子树
traverse(node.right); // 遍历右子树
result.push(node.val); // 访问根节点
}
traverse(root);
return result;
}
// 迭代法
function postorderTraversalIterative(root) {
if (root === null) return [];
const result = [];
const stack = [root];
let prev = null;
while (stack.length > 0) {
const curr = stack[stack.length - 1];
if (!prev || prev.left === curr || prev.right === curr) {
if (curr.left) {
stack.push(curr.left);
} else if (curr.right) {
stack.push(curr.right);
}
} else if (curr.left === prev) {
if (curr.right) {
stack.push(curr.right);
}
} else {
result.push(curr.val);
stack.pop();
}
prev = curr;
}
return result;
}
97.翻转二叉树
// 左右节点交换
var invertTree = function(root) {
resetTree(root)
function resetTree(node) {
if(!root){return root}
let left = node.left
let right = node.right
if(left||right){
node.right = left
node.left = right
// 交换后继续递归 左右子树
left&&resetTree(left)
right&&resetTree(right)
}
}
return root;
};