在二叉树的每一行中找到最大的值。
https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/
输入:
1
/ \
3 2
/ \ \
5 3 9
输出: [1, 3, 9]
每层中的最大元素, 自然想到了使用层次遍历, 但是层次遍历是不清楚层的开始和结束的, 所以还需要对层次遍历进行一下改造.
先说下标准的层次遍历, 需要使用一个队列结构
1. 先把根节点加入到队列中
2. 把队列的第一个元素出队, 出队的同时, 把此元素的left和right加入到队列末尾
3. 继续第二步直到队列为空. 出队的顺序即为层次遍历的结果.
我们可以观察下, 1->3->2->5->3->9, 上一层的节点出队完, 下一层的节点正好完全在队列中. 比如说, 1出队的时候, 3,2正好在队列中 , 3,2出队完, 5,3,9正好在队列中. 所以从根节点开始, 当上一层节点出队完成, 下一层节点完全在队列中.
我们可以修改下标准的层次遍历, 从根节点开始, 先记录下队列中的元素数量currentSize, 然后依次把0-currentSize之间的每个元素的left和right加入队列中, 这样的话[0,currentSize)就是上一层, [currentSize,array.count)就是下一层的所有元素, 然后找到[0,currentSize)中的最大值即可, 然后一次性出队完[0,currentSize)的全部. 这样层次遍历完就完成了.
func largestValues(_ root: TreeNode?) -> [Int] {
if root == nil {
return []
}
// 存放结果
var result = [Int]()
// 模拟队列结构
var array = [TreeNode]()
// 把根节点加入队列
array.append(root!)
while array.count > 0 {
var maxValue = Int.min
// [0,currentSize)是一层的全部数据, 把这些数据的左右孩子加入队列, 同时找出[0,currentSize)中的最大值
let currentSize = array.count
for i in 0..<currentSize {
let node = array[i]
if node.val > maxValue {
maxValue = node.val
}
if node.left != nil {
array.append(node.left!)
}
if node.right != nil {
array.append(node.right!)
}
}
// 一次性移除一层数据
array.removeFirst(currentSize)
// 添加该层的最大值到结果中
result.append(maxValue)
}
return result
}
其实这个也可以使用中序遍历(前序后续都可以)的, 只不过需要对每一个节点标识下所在的行数.
这个算法最主要的难点就是要知道每层有哪些元素, 我们通过正常的中序遍历, 在遍历每个节点时附加一个层数, 用一个result数组保存每层的最大值, 每个元素遍历时更新result中的值, 遍历完成, result也构建完成.
效率略差一点, 可能是差在递归调用上吧.
func largestValues(_ root: TreeNode?) -> [Int] {
if root == nil {
return []
}
var result = [Int]()
findMaxValue(root: root, result: &result, level: 0)
print(result)
return result
}
/// 中序遍历
/// - Parameters:
/// - root: 节点
/// - result: 保存结果的数组
/// - level: 当前节点所在的行
public func findMaxValue(root: TreeNode!, result: inout [Int], level: Int) {
if root == nil {
return
}
// 如果所在行已经有值了,更新值
if level<result.count {
result[level] = max(result[level], root.val)
} else {
// 这一行还没有值,把这个值认为是最大值
result.append(root.val)
}
// 中序遍历左右节点, 同时使行数增加
findMaxValue(root: root.left, result: &result, level: level+1)
findMaxValue(root: root.right, result: &result, level: level+1)
}