题目17: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
思路分析
方法一:递归+子问题思想
后续遍历:因为要返回子节点是否可以删除之后,再判断当前节点。
当前节点可以删除的条件是什么?
- 当前节点是叶子节点并且当前节点值等于
target即root->left == nullptr && root->right == nullptr && root->val == target - 当前节点的左右节点都可以删除并且当前节点值等于
target即rightv && leftv && root->val == target,其中rightv和leftv分别表示左右节点可以删除
删除节点要在父节点的位置进行删除。
左右子树返回是否可以删除,例如,左子树返回可以删除,那么就可以通过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…