【每日一题】 1110.删点成林

25 阅读1分钟

先上链接 leetcode.cn/problems/de…

题目描述

给出二叉树的根节点 root,树上每个节点都有一个不同的值。

如果节点值在 to_delete 中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合)。

返回森林中的每棵树。你可以按任意顺序组织答案。

  image.png

image.png 来源:力扣(LeetCode) 链接:leetcode.cn/problems/de… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

  1. 后序遍历

用后序遍历,从后向前检查节点的值是否在to_delete列表里 代码如下


func delNodes(root *TreeNode, to_delete []int) (res []*TreeNode) {
   deleteSet := make(map[int]bool)
   for _, v := range to_delete {
      deleteSet[v] = true
   }
   var dfs func(*TreeNode) *TreeNode
   dfs = func(p *TreeNode) *TreeNode {
      if p == nil {
         return nil
      }
      p.Left = dfs(p.Left)
      p.Right = dfs(p.Right)
      deleted := deleteSet[p.Val]
      if deleted {
         res = append(res, p.Left, p.Right)
         return nil
      } else {
         return p
      }
   }
   dfs(root)
   return
}

但是很遗憾,这种解法目前还有问题

输入[1,2,3,4,5,6,7] [3,5]

输出 [[],[],[6],[7]]

预期结果 [[1,2,null,4],[6],[7]]

  1. 官方推荐的isRoot 方法

在删除一个节点时,会多做一次是否为根结点的判断

func delNodes(root *TreeNode, to_delete []int) (res []*TreeNode) { 
    deleteSet := make(map[int]bool) 
    for _, v := range to_delete {
        deleteSet[v] = true 
    } 
    var dfs func(*TreeNode, bool) *TreeNode 
    dfs = func(p *TreeNode, isRoot bool) *TreeNode { 
        if p == nil { 
            return nil 
        } 
        deleted := deleteSet[p.Val] 
        p.Left = dfs(p.Left, deleted) 
        p.Right = dfs(p.Right, deleted) 
        if deleted { 
            return nil 
        } else { 
            if isRoot { 
                res = append(res, p) 
            } 
            return p 
        } 
    } 
    dfs(root, true) 
    return 
}