1123. 最深叶节点的最近公共祖先 - Kotlin DFS 深度优先搜索 递归+分类讨论

Smile_slime_47

Problem: 1123. 最深叶节点的最近公共祖先

思路

由于我们无法从子节点向上找回父节点,因此在这道题中明显判断节点的高度要比判断节点的深度更加方便,我们应当用一个数据结构将所有节点的高度存储下来。

基于DFS递归获取每个节点的高度:对于任意一个根节点,其高度等于左子树的高度和右子树的高度的较大值+1,对于叶子节点,其高度为1,因此当传入的节点为null时,应当返回0。用一个哈希表将每个节点的高度存储下来以便后续操作查询。

接下来从根节点开始进行递归:

  • 当当前节点的左子树高度和右子树高度相同时,说明当前节点即为所有最深节点的公共节点,返回当前节点即可
  • 当当前节点的左子树高度大于右子树高度时,说明最深叶节点均在左子树上,则递归到当前节点的左节点上
  • 当当前节点的左子树高度小于右子树高度时,说明最深叶节点均在右子树上,则递归到当前节点的右节点上
  • 当当前节点的左节点为null时,说明最深叶节点均在右子树上,则递归到当前节点的右节点上
  • 当当前节点的右节点为null时,说明最深叶节点均在左子树上,则递归到当前节点的左节点上
  • 当当前节点的左右节点均为null时,说明当前节点本身即为最深节点,返回当前节点——这只会出现在整棵树只有一个最深节点的情况下
  • 当当前节点为null时,说明当前传入的节点即为null,返回null——这只会出现在传入null样例的情况下

复杂度

  • 时间复杂度:

  • 空间复杂度:

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution
fun Solution.lcaDeepestLeaves(root: TreeNode?, map: HashMap<TreeNode, Int>? = null): TreeNode? {
if (map == null) {
val heightMap = HashMap<TreeNode, Int>()
freshDepth(heightMap, root)
return lcaDeepestLeaves(root, heightMap)
} else return when {
(root == null) ->
null
(root.left == null && root.right == null) ->
root
(root.left == null) ->
lcaDeepestLeaves(root.right, map)
(root.right == null) ->
lcaDeepestLeaves(root.left, map)
(map[root.left]!! == map[root.right]!!) ->
root
(map[root.left]!! > map[root.right]!!) ->
lcaDeepestLeaves(root.left, map)
(map[root.left]!! < map[root.right]!!) ->
lcaDeepestLeaves(root.right, map)
else ->
null
}
}

fun Solution.freshDepth(map: HashMap<TreeNode, Int>, root: TreeNode?): Int {
if (root == null) {
return 0
}
val height = Math.max(freshDepth(map, root.left), freshDepth(map, root.right)) + 1
map[root] = height
return height
}
Comments
On this page
1123. 最深叶节点的最近公共祖先 - Kotlin DFS 深度优先搜索 递归+分类讨论