如有一棵二叉树,删除其中的第
层节点:
1
/ \
1 1
/ \ /
1 1 1
/ \ \
1 1 1
\ /
1 1
其会变为如下四棵二叉树:
1
/ \
1 1
1 1 1
\ /
1 1
牛牛现在给你初始二叉树,以及表示删除第几层的删除序列
。牛牛希望能能将最后剩下的子树,按照根节点层序遍历的顺序返回子树数组。
1
/ \
1 1
/ \ /
1 1 1
/ \ \
1 1 1
\ /
1 1
1
/ \
1 1
1 1 1
\ /
1 1
{1,1,1,1,1,1,#,1,1,#,1,#,#,#,1,1},[3][{1,1,1},{1,#,1},{1,1},{1}]
其为如题意给定的二叉树所得到的子树序列。
{1,#,1,#,1,#,1,#,1},[2,4][{1},{1},{1}]
给定的为一条长度为的链,删去第
层与
层后剩下三个单节点子树。
。
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型vector
* @return TreeNode类vector
*/
vector<TreeNode*> deleteLevel(TreeNode* root, vector<int>& a) {
// write code here
vector<TreeNode*> ans;
unordered_map<int,int> m;
m[0]=1;
for(auto num:a)
m[num]=1;
queue<pair<TreeNode*, int>> que;
que.push(make_pair(root, 1));
while(!que.empty())
{
pair<TreeNode*, int> p = que.front();
que.pop();
TreeNode* t = p.first;
int high = p.second;
if(t==nullptr)
continue;
if(m.find(high-1)!=m.end() && m.find(high)==m.end())
ans.push_back(t);
que.push(make_pair(t->left, high+1));
que.push(make_pair(t->right, high+1));
if(m.find(high+1)!=m.end())
{
t->left=nullptr;
t->right=nullptr;
}
}
return ans;
}
}; //1.使用HashSet记录要删除的深度,注意要添加第0层,因为根节点也可以看作被删掉上一层的。
//2.使用BFS常规模板,并记录层序深度
//3.hashset.contains(depth) 来判断是否需要加入该层的节点(各个子树的头节点)
//4.处于要删除的层的上一层,因为已经将左右节点入队了,因此只需要将左右指针置空jiu'ke'yu public ArrayList<TreeNode> deleteLevel (TreeNode root, ArrayList<Integer> a) {
//记录要删除的深度
Set<Integer> set = new HashSet<Integer>();
for (int num: a)
set.add(num);
//这里要加0,因为根节点是看作被被删除上一层的
set.add(0);
ArrayList<TreeNode> list = new ArrayList<TreeNode>();
//BFS的模板
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int depth = 0;
while(!queue.isEmpty()){
int size = queue.size();
depth++;
for (int i = 0; i < size; i++){
TreeNode node = queue.poll(); //注意这里弹出的是上一层的节点
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
//特殊例子 depth=2也就是在第二层,根节点要入链表
//其它情况 上一层被删除了,那么就要加上这一层的头节点
if (set.contains(depth-1)&&!set.contains(depth)){
list.add(node);
}
//要删除的上一层(因为上一层的左右节点都已经入队,此时我们只需要将左右指针置空即可)
if(!set.contains(depth)&&set.contains(depth+1)){
node.left = null;
node.right = null;
}
}
}
return list;
} /**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型vector
* @return TreeNode类vector
*/
typedef pair<TreeNode*, int> PII;
vector<TreeNode*> deleteLevel(TreeNode* root, vector<int>& a) {
// write code here
vector<TreeNode*> ans;
unordered_map<int,int> m;
m[0]=1; // 根节点是第一层,第0层是没有的,相当于被删除了的,所以设置为1,加这个特判后面如果根节点不删除的话,根节点才能够顺理成章的被录入答案ans中,以免漏掉根节点。
for(auto num:a)
m[num]=1; // 将要删除的层数映射为1
queue<PII> q;
q.push({root, 1});
while(q.size()) // 通过while循环进行层序遍历
{
PII p = q.front();
q.pop();
TreeNode* t = p.first;
int high = p.second;
if(t == nullptr) // 如果这个节点是空的话(即不存在的话),就不用考虑它的左右子树了,因为空的是啥都没有的
continue;
if(m.find(high-1) != m.end() && m.find(high) == m.end()) // 挺过了前面的判断,到这里来的节点都不是空的了,那就判断它的上一个层是否为空,如果上一层为空,那么本层的所有节点就都可以作为根节点录入,并且一定都是树,有多少个根节点就有多少棵树
ans.push_back(t); // 既然一定是根节点,那就一定是答案的里的一棵树,将其添加到ans中
/*
map的find函数,如果找到了,就会返回一个iterator,m.end()表示容器末尾的下一位,如果iterator没有到容器末尾的话,就表明找到了
iterator如果指向了容器末尾的下一位,则表示整个容器都已经搜索过了,没有找到high的映射
find里面填的是map的第一个参数,如果找到的话,iterator是指向第二个参数,也就是第一个参数的映射
*/
q.push({t->left, high+1}); // 这个while循环的本质就是在不断把一个节点的左节点和右节点添加到队列中,让while循环完成层序遍历的任务
q.push({t->right, high+1}); // 队列中放的pair的第一个参数是一个节点,第二个参数是这个节点所在的层数,根节点是第一层,往下层数增大
if(m.find(high+1) != m.end()) // 如果下层要被删掉,则此节点的左右节点都为空
{
t->left = nullptr;
t->right = nullptr;
}
}
return ans;
}
};
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型vector
* @return TreeNode类vector
*/
typedef pair<TreeNode*, int> PII;
vector<TreeNode*> deleteLevel(TreeNode* root, vector<int>& a) {
// write code here
vector<TreeNode*> ans;
queue<PII> q;
q.push({root, 1});
unordered_map<int, int> m;
m[0] = 1;
for(auto c : a) {
m[c] = 1;
}
while(q.size()) {
auto p = q.front();
q.pop();
auto t = p.first;
auto high = p.second;
// 无论如果,都是要层序遍历完整棵树的所以,要把左右子树添加进队列
if(t -> left != nullptr)
q.push({t->left, high + 1});
if(t -> right != nullptr)
q.push({t->right, high +1});
if(m.count(high + 1)){ // 截断,把树分开
t->left = nullptr; // 这里的t->left为空,不影响前面的t->left,因为它已经进队列了
t->right = nullptr; // 这里的t->left == nullptr更多是为了断开连接,让t这个节点指向空就行,至于后面要如何遍历,前面已经将t->left添加到队列中去,前面的t->left表示的是t的左子树的根节点
// t->left是一个指针,它可以指向空,也可以指向一棵树,前面的t->left就是指向t的左子树,那这样的话,就相当于t的左子树的根节点
// 而这里是让t->left指针指向空,目的是为了断开与后面子树的联系,相当于就删除了high+1这一层了
// 注意!!一定要让t->left和t->right先进队列,再将其删除,因为只有这样,才能够遍历树,如果先删了,就断层,无法遍历整棵树了
}
if(m.count(high -1) && !m.count(high)) {
ans.push_back(t);
}
}
return ans;
}
}; # class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param root TreeNode类
# @param a int整型一维数组
# @return TreeNode类一维数组
#
class Solution:
def deleteLevel(self , root: TreeNode, a: List[int]) -> List[TreeNode]:
# write code here
# 只需要将list型的a转换成set类型,就可以使得a在查找时时间复杂度降低
a = set(a)
def bfs(root,a):
if root is None:
return
res = []
count = 1
if 1 not in a:
res = [root]
queue = [root]
while len(queue)!=0:
temp = []
for q in queue:
if q.left is not None:
temp.append(q.left)
if q.right is not None:
temp.append(q.right)
if (count+1) in a:
q.left=None
q.right=None
if count in a and (count+1) not in a:
res+=temp
count += 1
queue = temp
return res
return bfs(root,a) public ArrayList<TreeNode> deleteLevel (TreeNode root, ArrayList<Integer> a) {
Set<Integer> set = new HashSet<>();
for (int num : a) set.add(num);
set.add(0);
Queue<TreeNode> queue = new LinkedList<>();
ArrayList<TreeNode> list = new ArrayList<>();
queue.add(root);
int depth = 0;
while (!queue.isEmpty()) {
int size = queue.size();
depth++;
while (size-- > 0) {
TreeNode node = queue.poll();
if (node.left != null)
queue.add(node.left);
if (node.right != null)
queue.add(node.right);
if (set.contains(depth - 1) && !set.contains(depth))
list.add(node);
if (!set.contains(depth) && set.contains(depth + 1)) {
node.left = null;
node.right = null;
}
}
}
return list;
} import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型ArrayList
* @return TreeNode类ArrayList
*/
public ArrayList<TreeNode> deleteLevel (TreeNode root, ArrayList<Integer> a) {
// write code here
ArrayList<TreeNode> res = new ArrayList<>();
if(root == null){
return res;
}
if(a.size() == 0){
res.add(root);
return res;
}
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
List<ArrayList<TreeNode>> lists = new ArrayList<>();
while(!q.isEmpty()){
int size = q.size();
ArrayList<TreeNode> list = new ArrayList<>();
for(int i = 0; i < size; ++i){
root = q.poll();
list.add(root);
if(root.right != null){
q.offer(root.right);
}
if(root.left != null){
q.offer(root.left);
}
}
lists.add(list);
}
//将a倒序排序
Collections.sort(a, (o1, o2) -> {return o2 - o1;});
int size = lists.size();
for(int level : a){
//对于删除层level,需要将第level + 1层每个节点看成1棵子树,同时将level - 1层的子节点置为null
//但lists中下标从0开始,所以第level层对应下标为level - 1,
//第level + 1层对应下标为level, 第level - 1层对应level - 2
if(lists.size() > level){
//判断第level + 1层是否是移除的
if(!a.contains(level + 1)){
res.addAll(lists.get(level));
}
}
if(level > 1){
//将第level - 1层的子节点置为null
for(TreeNode node : lists.get(level - 2)){
node.left = null;
node.right = null;
}
}
}
//如果第1层不用删除,此时还需要将其添加到res中
if(a.get(a.size() - 1) != 1){
res.addAll(lists.get(0));
}
//将结果倒序(因为是逆序遍历level,再添加到res中的)
Collections.reverse(res);
return res;
}
} class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型vector
* @return TreeNode类vector
*/
vector deleteLevel(TreeNode* root, vector& a) {
// write code here
unordered_set dic(a.begin(),a.end());
vector ans;
int level=0;
TreeNode* dummp=new TreeNode(0);
dummp->left=root;
queue q;
q.push(dummp);
if(!dic.count(1))ans.push_back(root);
while(!q.empty()){
int sz=q.size();
for(int i=0;i<sz;i++){
TreeNode* tmp=q.front();q.pop();
if(tmp->left){
q.push(tmp->left);
}
if(tmp->right){
q.push(tmp->right);
}
if(dic.count(level)&&!dic.count(level+1)){
if(tmp->left)ans.push_back(tmp->left);
if(tmp->right)ans.push_back(tmp->right);
}
if(dic.count(level+1)){
tmp->left=nullptr;
tmp->right=nullptr;
}
}
level++;
}
return ans;
}
};
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型ArrayList
* @return TreeNode类ArrayList
*/
private ArrayList<TreeNode> res;
public ArrayList<TreeNode> deleteLevel (TreeNode root, ArrayList<Integer> a) {
// write code here
res = new ArrayList<>();
Set<Integer> set = new HashSet<>();
for(int i = 0; i < a.size(); i++) set.add(a.get(i));
set.add(0);
Queue<TreeNode> q = new LinkedList<>();
int height = -1;
TreeNode newRoot = new TreeNode(0);
newRoot.left = root;
q.add(newRoot);
while(!q.isEmpty()) {
int size = q.size();
height++;
while(size-- > 0) {
TreeNode front = q.poll();
if(front.left != null) q.add(front.left);
if(front.right != null) q.add(front.right);
if(!set.contains(height) && set.contains(height + 1)) {
front.left = null;
front.right = null;
}
if(set.contains(height) && !set.contains(height + 1)) {
if(front.left != null) {
res.add(front.left);
}
if(front.right != null) {
res.add(front.right);
}
}
}
}
return res;
}
} class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型vector
* @return TreeNode类vector
*/
map<int, vector<TreeNode *>> cache;
unordered_set<int> st;
vector<TreeNode *> deleteLevel(TreeNode *root, vector<int> &a) {
// write code here
st.insert(0);
for (int i : a) {
st.insert(i);
}
dfs(root, 1);
vector<TreeNode *> ans;
for (auto &kv : cache) {
for (auto &v : kv.second) {
ans.emplace_back(v);
}
}
return ans;
}
void dfs(TreeNode *root, int depth) {
if (root == nullptr) {
return;
}
bool preDel = (st.find(depth - 1) != st.end());
bool nowDel = (st.find(depth) != st.end());
bool nxtDel = (st.find(depth + 1) != st.end());
if ((!nowDel) && preDel) {
cache[depth].emplace_back(root);
}
dfs(root->left, depth + 1);
dfs(root->right, depth + 1);
if (nxtDel) {
root->left = nullptr;
root->right = nullptr;
}
}
}; class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型vector
* @return TreeNode类vector
*/
// 在a中查找是否包含目标值
bool find(vector<int> a,int target){
for(int i=0;i<a.size();i++){
if(a[i] == target){
return true;
}
}
return false;
}
vector<TreeNode*> deleteLevel(TreeNode* root, vector<int>& a) {
queue<pair<TreeNode*,int>> q; //节点和层数
q.push({root,1});
vector<TreeNode*> ans;
if (!find(a,1)){
ans.push_back(root);
}
while(!q.empty()){
auto [node,deep] = q.front();
q.pop();
if (node == nullptr){
continue;
}
// 如果这层的上一层被删除了并且这层不需要被删,它就是需要的答案
if (find(a, deep - 1) && !find(a, deep)){
ans.push_back(node);
}
q.push({node->left, deep + 1});
q.push({node->right, deep + 1});
// 如果这层的下一层被删除了,这层就是末尾,左右节点全置空
if (find(a, deep + 1)){
node->left = nullptr;
node->right = nullptr;
}
}
return ans;
}
};
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型ArrayList
* @return TreeNode类ArrayList
*/
public ArrayList<TreeNode> deleteLevel (TreeNode root, ArrayList<Integer> a) {
// write code here
ArrayList<TreeNode> res= new ArrayList<>();
if (root==null) return res;
//这是二叉树行遍历 把每一行称之为索引行
List<List<TreeNode>> help = levelorder(root);
//这个变量是指向了当前树的根节点所在的层数
//举个例子 假如第3层被切掉了(索引为2的行)
//现在rootIndex还在0 把0行的树节点都假如到res集合中
//然后更新rootIndex变成3=(2+1) 下次就从3开始 3上面的不考虑了
//还不明白就看下面代码
int rootIndex=0;
Collections.sort(a);
for (int cur : a) {
//对于每个cur 把他变成索引行对应的值 也就是cur-1
cur=cur-1;
//如果当前切除了根 不用管直接下一位
if (cur==rootIndex){
rootIndex++;
continue;
}
//不是的话就要找到切除行的上一行 然后把每个节点的左后孩子都置null
List<TreeNode> list = help.get(cur - 1);
for (TreeNode node : list) {
node.left=null;
node.right=null;
}
//然后加入当前rootIndex所在的节点 继续下一轮
for (TreeNode node : help.get(rootIndex)) {
res.add(node);
}
rootIndex=cur+1;
}
//最后看情况做节点的收尾补偿工作
if (rootIndex<help.size()){
for (TreeNode node : help.get(rootIndex)) {
res.add(node);
}
}
return res;
}
//这个函数是二叉树行遍历 大家肯定都会
public List<List<TreeNode>> levelorder(TreeNode root) {
List<List<TreeNode>> res = new ArrayList<>();
if (root == null) return res;
Deque<TreeNode> q = new LinkedList<>();
q.addLast(root);
while (!q.isEmpty()) {
int size = q.size();
List<TreeNode> list = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode cur = q.pollLast();
list.add(cur);
if (cur.left != null) q.addFirst(cur.left);
if (cur.right != null) q.addFirst(cur.right);
}
res.add(list);
}
return res;
}
} import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param a int整型ArrayList
* @return TreeNode类ArrayList
*/
public ArrayList<TreeNode> deleteLevel (TreeNode root, ArrayList<Integer> a) {
// write code here
HashSet<Integer> set = new HashSet<>();
for(int val : a) set.add(val);
set.add(0);
ArrayList<TreeNode> list = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int preNum = 1,current_num = 0,current_deep = 1;
while(queue.size() != 0){
TreeNode node = queue.poll();
--preNum;
if(node.left != null){
queue.offer(node.left);
++current_num;
}
if(node.right != null){
queue.offer(node.right);
++current_num;
}
if(set.contains(current_deep-1) && set.contains(current_deep) == false){
list.add(node);
}
if(set.contains(current_deep) == false && set.contains(current_deep+1)){
node.left = null;
node.right = null;
}
if(preNum == 0){
preNum = current_num;
current_num = 0;
++current_deep;
}
}
return list;
}
}