持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
示例1:
输入:root = [1,3,2,5,3,null,9]
输出:[1,3,9]
示例2:
输入:root = [1,2,3]
输出:[1,3]
深度优先搜索
我们用树的「先序遍历」来进行「深度优先搜索」处理,并用 来标记遍历到的当前节点的高度。当遍历到 高度的节点就判断是否更新该层节点的最大值。
var largestValues = function(root) {
if (!root) {
return [];
}
const res = [];
const dfs = (res, root, curHeight) => {
if (curHeight === res.length) {
res.push(root.val);
} else {
res.splice(curHeight, 1, Math.max(res[curHeight], root.val));
}
if (root.left) {
dfs(res, root.left, curHeight + 1);
}
if (root.right) {
dfs(res, root.right, curHeight + 1);
}
}
dfs(res, root, 0);
return res;
};
复杂度分析
- 时间复杂度: ,其中 为二叉树节点个数。二叉树的遍历中每个节点会被访问一次且只会被访问一次。
- 空间复杂度:。其中 表示二叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于二叉树的高度。
广度优先搜索
我们也可以用「广度优先搜索」的方法来解决这道题目。「广度优先搜索」中的队列里存放的是「当前层的所有节点」。每次拓展下一层的时候,不同于「广度优先搜索」的每次只从队列里拿出一个节点,我们把当前队列中的全部节点拿出来进行拓展,这样能保证每次拓展完的时候队列里存放的是下一层的所有节点,即我们是一层一层地进行拓展,然后每一层我们用 来标记该层节点的最大值。当该层全部节点都处理完后, 就是该层全部节点中的最大值。
var largestValues = function(root) {
if (!root) {
return [];
}
const res = [];
const queue = [root];
while (queue.length) {
let len = queue.length;
let maxVal = -Number.MAX_VALUE;
while (len > 0) {
len--;
const t = queue.shift();
maxVal = Math.max(maxVal, t.val);
if (t.left) {
queue.push(t.left);
}
if (t.right) {
queue.push(t.right);
}
}
res.push(maxVal);
}
return res;
};
复杂度分析
- 时间复杂度:,其中 为二叉树节点个数,每一个节点仅会进出队列一次。
- 空间复杂度: ,存储二叉树节点的空间开销。