一、二叉树的层序遍历
题目(LT102. 二叉树的层序遍历)
给你一个二叉树,请你返回其按 层序遍历 得到的节点值(即逐层地,从左到右访问所有节点)。
示例:
二叉树:[3,9,20,null,null,15,7],
3
/ \ 9 20 / \ 15 7
返回其层序遍历结果:
[ [3], [9,20], [15,7] ]
解题思路
- 层序遍历顺序就是广度优先遍历;
- 不过在遍历时候需要记录当前节点所处的层级,方便将其添加到不同数组中。
方案一
var levelOrder = function(root) {
if(!root) return []
const stack = [[root,0]] // 采用原数组方式,1代表层级
const result = []
while(stack.length){
const [node, level] = stack.shift()
if(result[level]) {
result[level].push(node.val)
} else {
result[level] = [node.val]
}
if(node.left) stack.push([node.left, level + 1])
if(node.right) stack.push([node.right, level + 1])
}
return result
};
方案二
广度优先遍历在不断地将老节点出队,并且在不断地将老节点的孩子入队。如果我们能保证在每次的while循环迭代里,都能把所有的老人都出队,并把下一层级的所有节点都入队的话,就可以确保while循环体内刚进来的时候队列里都是同一层级的节点。
var levelOrder = function(root) {
if(!root) return []
const stack = [root]
const result = []
while(stack.length){ // 每次遍历是对层级做遍历
let length = stack.length
result.push([])
// 将同一层级的所有节点都推到这个数组里
while(length--) {
const node = stack.shift()
result[result.length - 1].push(node.val) // 利用数组自身长度来处理层级
if(node.left) stack.push(node.left)
if(node.right) stack.push(node.right)
}
}
return result
};
因为是广度优先遍历,时间复杂度是O(N),空间复杂度也是O(N)。
二、路径总和
题目(LT112. 路径总和)
给定二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。
叶子节点是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22 输出:true
示例 2:
输入:root = [1,2,3], targetSum = 5 输出:false
示例 3:
输入:root = [1,2], targetSum = 0 输出:false
解题思路
- 在深度优先遍历的过程中,记录当前路径的节点值的和。
在叶子节点处,判断当前路径的节点值得和是否等于目标值
var hasPathSum = function(root, targetSum) {
if(!root) return false
let result = false
const dfs = (root, sum)=> {
// 只有在叶子节点处才会进行判断。
if(!root.left && !root.right && sum === targetSum) {
result = true
}
if(root.left) dfs(root.left, sum + root.left.val)
if(root.right) dfs(root.right, sum + root.right.val)
}
dfs(root, root.val)
return result
};
时间复杂度是O(N)。由于使用了递归,递归会使用函数调用堆栈,所以空间复杂度也是O(N)。