Leetcode 366. 寻找二叉树的叶子结点

215 阅读1分钟

题目链接:leetcode.cn/problems/fi…

需要解决的问题

在本题中我们需要思考

  1. 如何通过叶子节点找到其对应的父节点?
  2. 如何将子树的父节点设置为叶子节点?

为什么要解决上面两个问题呢?

  1. 我们可以根据深度遍历找到相应的叶子结点,但是没有遍历方法可以让我们通过叶子结点找到根节点,所以就需要把叶子结点和它的父节点之间建立对应关系。
  2. 我们需要得知父节点是否可以变成叶子结点,父节点变成叶子节点的条件就是它的子节点已经被删除完毕了。所以需要记录一下根节点对应的子节点的个数。

解题思路

根据我们上面提出的问题设计相应的解题思路

  1. 通过先序遍历的方式建立父节点和子节点之间的对应关系
  2. 通过逆序遍历的方式从子节点向根节点遍历的方式来模拟删除叶子节点的流程。

解题代码

func findLeaves(root *TreeNode) [][]int {
   if root == nil {
      return nil
   }
   edge := make(map[*TreeNode]*TreeNode)
   ks := make(map[*TreeNode]int)
   leave := []*TreeNode{}

   var preFunc func(node *TreeNode)

   preFunc = func(node *TreeNode) {
      if node == nil {
         return
      }
      if node.Left == nil && node.Right == nil {
         leave = append(leave, node)
      }
      if node.Left != nil {
         edge[node.Left] = node
         ks[node]++
      } else {
         ks[node] = ks[node]
      }

      if node.Right != nil {
         edge[node.Right] = node
         ks[node]++
      } else {
         ks[node] = ks[node]
      }

      preFunc(node.Left)
      preFunc(node.Right)
   }

   preFunc(root)

   result := [][]int{}

   for len(leave) != 0 {
      tmp := []int{}
      length := len(leave)
      for i := 0; i < length; i++ {
         cur := leave[0]
         leave = leave[1:]
         tmp = append(tmp, cur.Val)
         ks[edge[cur]]--
         if ks[edge[cur]] == 0 {
            leave = append(leave, edge[cur])
         }
      }
      result = append(result, tmp)
   }

   return result
}