這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰前端
分層
數據的抽象模型例:node
{
value: "zhe jiang",
label: "zhe jiang",
children: [
value: "hangzhou",
label: "hangzhou",
children: [...]
]
}
複製代碼
以下分別是兩種方式 遍歷的順序。json
const tree = {
val: "a",
children: [
{
val: "b",
children: [
{ val: "d", children: [] },
{ val: "e", children: [] }
]
},
{
val: "c",
children: [
{ val: "f", children: [] },
{ val: "g", children: [] }
]
}
]
}
const dfs = root => {
console.log(root.val); // a,b,d,e,c,f,g
root.children.forEach(dfs)
}
複製代碼
const tree = {
val: "a",
children: [
{
val: "b",
children: [
{ val: "d", children: [] },
{ val: "e", children: [] }
]
},
{
val: "c",
children: [
{ val: "f", children: [] },
{ val: "g", children: [] }
]
}
]
}
經過隊列的方式,將先遍歷的放在隊首,後面層級的放在隊尾
const bfs = root => {
const q = [root]
while(q.length > 0) {
const n = q.shift()
console.log(n.val)
n.children.forEach(child => {
q.push(child)
})
}
}
複製代碼
左
子樹進行先序遍歷右
子樹進行先序遍歷const bt = {
val: 1,
left: {
val: 2,
left: {
val: 4,
left: null,
right: null
},
right: {
val: 5,
left: null,
right: null
}
},
right: {
val: 3,
left: {
val: 6,
left: null,
right: null
},
right: {
val: 7,
left: null,
right: null
}
}
}
// 遞歸版:
const preorder = root => {
if (!root) return
console.log(root.val) // 1245 367
preorder(root.left)
preorder(root.right)
}
// 非遞歸版:
const preorder = root => {
if (!root) return
const stack = [root]
while(stack.length) {
const n = stack.pop()
console.log(n.val)
if (n.right) stack.push(n.right)
if (n.left) stack.push(n.left)
}
}
複製代碼
const bt = {
val: 1,
left: {
val: 2,
left: {
val: 4,
left: null,
right: null
},
right: {
val: 5,
left: null,
right: null
}
},
right: {
val: 3,
left: {
val: 6,
left: null,
right: null
},
right: {
val: 7,
left: null,
right: null
}
}
}
// 遞歸版:
const inorder = root => {
if (!root) return
inorder(root.left)
console.log(root.val)
inorder(root.right)
}
複製代碼
const bt = {
val: 1,
left: {
val: 2,
left: {
val: 4,
left: null,
right: null
},
right: {
val: 5,
left: null,
right: null
}
},
right: {
val: 3,
left: {
val: 6,
left: null,
right: null
},
right: {
val: 7,
left: null,
right: null
}
}
}
const postorder = root => {
if (!root) return
postorder(root.left)
postorder(root.right)
console.log(root.val)
}
複製代碼
LeetCode-104: 二叉樹最大深度markdown
**示例:**\
給定二叉樹 `[3,9,20,null,null,15,7]`,
3
/ \
9 20
/ \
15 7
/** * 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) {
let res = 0;
const dfs = (n, l) => {
if (!n) return;
res = Math.max(res, l)
dfs(n.left, l + 1);
dfs(n.right, l + 1);
}
dfs(root, 1);
return res
};
複製代碼
輸入:root = [3,9,20,null,null,15,7]
輸出:2
示例 2:
輸入:root = [2,null,3,null,4,null,5,null,6]
輸出:5
來源:力扣(LeetCode)
/** * 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 minDepth = function(root) {
if (!root) return 0;
let stack = [ [root, 1] ]
while(stack.length) {
const [n, l] = stack.shift();
console.log(n.val, l)
if (!n.left && !n.right) return l
if (n.left) stack.push([n.left, l + 1])
if (n.right) stack.push([n.right, l + 1])
}
};
複製代碼
示例:
二叉樹:[3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其層序遍歷結果:
[
[3],
[9,20],
[15,7]
]
來源:力扣(LeetCode)
/** * 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 q = [ [root, 0] ]
const res = []
while(q.length) {
const [n, level] = q.shift()
if (!res[level]) {
res.push([n.val])
} else {
console.log(res, level)
res[level].push(n.val)
}
if (n.left) q.push([n.left, level + 1])
if (n.right) q.push([n.right, level + 1])
}
return res
};
複製代碼
輸入:root = [1,null,2,3]
輸出:[1,3,2]
示例 2:
輸入:root = []
輸出:[]
示例 3:
輸入:root = [1]
輸出:[1]
來源:力扣(LeetCode)
/**
* 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 inorderTraversal = function(root) {
const res = []
const rec = n => {
if (!root) return
rec(n.left)
res.push(n.val)
rec(n.right)
}
rec(root)
return res
};
複製代碼
輸入: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
輸出: true
複製代碼
輸入:root = [1,2,3], targetSum = 5
輸出:false
示例 3:
輸入:root = [1,2], targetSum = 0
輸出:false
來源:力扣(LeetCode)
/**
* 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;
let res = false
const dfs = (n, s) => {
if (!n.left && !n.right && s === targetSum) {
res = true
}
if (n.left) dfs(n.left, s + n.left.val)
if (n.right) dfs(n.right, s + n.right.val)
}
dfs(root, root.val)
return res
};
複製代碼
const json = {
a: { b: { c: 1 } } ,
d: [1, 2]
}
const dfs = (n, path) => {
if (!n) return
console.log(n, path)
Object.keys(n).forEach(k => {
dfs(n[k], path.concat(k))
})
}
dfs(json, [])
複製代碼
總結:this
- 樹 是一種分層的數據抽象模型
- 樹的經常使用操做:深度/廣度優先遍歷、先中後序遍歷...