二叉树_题目17:1325. 删除给定值的叶子节点

64 阅读3分钟

题目17:1325. 删除给定值的叶子节点

1325. 删除给定值的叶子节点

同类题目

前置知识

题目描述

给你一棵以 root 为根的二叉树和一个整数 target ,请你删除所有值为 target叶子节点

注意,一旦删除值为 target 的叶子节点,它的父节点就可能变成叶子节点;如果新叶子节点的值恰好也是 target ,那么这个节点也应该被删除。

也就是说,你需要重复此过程直到不能继续删除。

示例 1:

 输入:root = [1,2,3,2,null,2,4], target = 2
 输出:[1,null,3,null,4]
 解释:
 上面左边的图中,绿色节点为叶子节点,且它们的值与 target 相同(同为 2 ),它们会被删除,得到中间的图。
 有一个新的节点变成了叶子节点且它的值与 target 相同,所以将再次进行删除,从而得到最右边的图。

示例 2:

 输入:root = [1,3,3,3,2], target = 3
 输出:[1,3,null,null,2]

示例 3:

 输入:root = [1,2,null,2,null,2], target = 2
 输出:[1]
 解释:每一步都删除一个绿色的叶子节点(值为 2)。

提示:

  • 树中节点数量的范围是 [1, 3000]
  • 1 <= Node.val, target <= 1000

思路分析

方法一:递归+子问题思想

后续遍历:因为要返回子节点是否可以删除之后,再判断当前节点。

当前节点可以删除的条件是什么?

  • 当前节点是叶子节点并且当前节点值等于targetroot->left == nullptr && root->right == nullptr && root->val == target
  • 当前节点的左右节点都可以删除并且当前节点值等于targetrightv && leftv && root->val == target ,其中rightvleftv 分别表示左右节点可以删除

删除节点要在父节点的位置进行删除

左右子树返回是否可以删除,例如,左子树返回可以删除,那么就可以通过root->left == nullptr 来把左子树删除。

程序代码

方法一

 // https://leetcode.cn/problems/delete-leaves-with-a-given-value/description/
 // 1325. 删除给定值的叶子节点
 #include<iostream>
 #include<vector>
 using namespace std;
 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 };
 ​
 class Solution {
 public:
     bool travel(TreeNode* root, int target)
     {
         // 如果是叶子节点并且叶子节点的值等于target,返回可以删除
         if(root->left == nullptr && root->right == nullptr)
         {
             return root->val == target;
         }
 ​
         // 初始化为true, 左右为空时
         bool leftv = true;
         bool rightv = true;
         if(root->left)
         {
             leftv = travel(root->left,target);
             if(leftv)
             {
                 root->left = nullptr;
             }
         }
         if(root->right)
         {
             rightv = travel(root->right,target);
             if(rightv)
             {
                 root->right = nullptr;
             }
         }
         // 当前节点的左右节点都可以删除并且当前节点值等于target  
         return rightv && leftv && root->val == target;
         
     }
 ​
     TreeNode* removeLeafNodes(TreeNode* root, int target) {
         // 所有节点都删除了,那么root 也置空
         if(travel(root,target))
         {
             root = nullptr;
         }
         return root;
     }
 };

代码优化

 class Solution {
 public:
     TreeNode* removeLeafNodes(TreeNode* root, int target) {
         if (!root) {
             return nullptr;
         }
         root->left = removeLeafNodes(root->left, target);
         root->right = removeLeafNodes(root->right, target);
         if (!root->left && !root->right && root->val == target) {
             return nullptr;
         }
         return root;
     }
 };

复杂度分析

时间复杂度:构造过程是 O(N),其中 n 是二叉树中的节点个数,每个节点都会遍历一次。

空间复杂度:构造过程是O(logN) ,其中logN 为二叉树的高度。

题目感悟

要删除节点一定是左右子树返回后,在父节点的位置删除。

更多相关知识:github.com/pingguo1987…