vlambda博客
学习文章列表

582,DFS解二叉树剪枝

The higher I got, the more amazed I was by the view. 

我爬得越高,越为眼前的风景所惊叹。

问题描述



来源:LeetCode第814题

难度:中等


给定二叉树根结点root,此外树的每个结点的值要么是0,要么是1。返回移除了所有不包含1的子树的原二叉树


( 节点X的子树为X本身,以及所有X的后代。)


示例1:

输入: [1,null,0,0,1]

输出: [1,null,0,null,1]

 

解释

只有红色节点满足条件“所有不包含 1 的子树”。

右图为返回的答案。

示例2:

输入: [1,0,1,0,0,0,1]

输出: [1,null,1,null,1]

582,DFS解二叉树剪枝

示例3:

输入: [1,1,0,1,1,0,1,0]

输出: [1,1,0,1,1,null,1]

582,DFS解二叉树剪枝


说明:

  • 给定的二叉树最多有200个节点。

  • 每个节点的值只会为0或1。


DFS解决



这题是说如果二叉树的任一节点的左子树都是0,就把他的左子树删除,同理如果右子树都是0,也把他的右子树给删除。


这题常规思路是从根节点开始统计他的左右子树节点是否都是0,如果任一子树的所有节点都是0,就把他给删除。否则不能删除,然后再统计不能删除节点的子节点……,那这样的话工作量就非常大,并且还会出现大量重复计算,如下图所示:

582,DFS解二叉树剪枝

582,DFS解二叉树剪枝

582,DFS解二叉树剪枝

上面方式明显是行不通的。我们可以这样来思考一下,从上到下删不行,那么从下到上呢,如果是叶子节点并且值为0,我们就把他给删除,否则不要删除,看下视频

582,DFS解二叉树剪枝

看到这里大家可能就明白了,这就是二叉树的后续遍历,我们来看下代码

 1public TreeNode pruneTree(TreeNode root) {
2    if (root == null)
3        return null;
4    //这里要注意,当前节点可能不是叶子节点,但如果他的子节点
5    //都删除完了,它就变成了叶子节点。
6    //剪枝左子树
7    root.left = pruneTree(root.left);
8    //剪枝右子树
9    root.right = pruneTree(root.right);
10    //如果叶子节点的值是0,就把他给删除,返回一个空的节点
11    if (root.left == null && root.right == null && root.val == 0)
12        return null;
13    //否则不要删除,直接返回即可
14    return root;
15}

时间复杂度:O(n),n是二叉树中节点的个数。

空间复杂度:O(h),h是树的高度,也是递归的深度。




你点的每个赞,我都认真当成了喜欢