LeetCode 366. 寻找二叉树的叶子节点(上下翻转二叉树+BFS)

文章目录

1. 题目

给你一棵二叉树,请按以下要求的顺序收集它的全部节点:

  • 依次从左到右,每次收集并删除所有的叶子节点
  • 重复如上过程直到整棵树为空
示例:
输入: [1,2,3,4,5]
  
          1
         / \
        2   3
       / \     
      4   5    

输出: [[4,5,3],[2],[1]]
 
解释:

1. 删除叶子节点 [4,5,3] ,得到如下树结构:

          1
         / 
        2          
 

2. 现在删去叶子节点 [2] ,得到如下树结构:

          1          
 

3. 现在删去叶子节点 [1] ,得到空树:

          []         

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-leaves-of-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

类似题目:LeetCode 156. 上下翻转二叉树(DFS)*

  • 先自底向上,翻转二叉树,把子节点的 left,指向父节点
  • 同时记录父节点有多少个子节点(0,1,2,)
  • 把叶子节点加入队列
  • 开始BFS,出队一个,就把该节点的 left (原来的父节点的子节点计数 -1)
  • 当节点的子节点计数为0时,它就变成了叶子节点,可以入队了
class Solution {
    vector<vector<int>> ans;
    queue<TreeNode*> q;
    unordered_map<TreeNode*, int> map;//父节点底下挂着几个子节点
public:
    vector<vector<int>> findLeaves(TreeNode* root) {
        reverse(root);//上下翻转二叉树
        while(!q.empty())
        {
        	int size = q.size(), i = 0;
        	vector<int> lv(size);
        	while(size--)
        	{
        		TreeNode *cur = q.front();
        		q.pop();
        		map[cur->left]--;//原父节点的子节点计数-1
        		lv[i++] = cur->val;//当前值写入答案
        		if(cur->left && map[cur->left]==0)//父节点计数为0,可以入队
        			q.push(cur->left);
        	}
        	ans.push_back(lv);
        }
        return ans;
    }
    TreeNode* reverse(TreeNode* root)
    {
    	if(!root) return NULL;
    	auto l = root->left;
    	auto r = root->right;
    	if(!l && !r)
    		q.push(root);//叶子节点加入队列
    	map[root] += (l?1:0) + (r?1:0);//记得加括号,子节点个数
    	root->left = NULL;//断开子节点
    	root->right = NULL;
    	auto lc = reverse(l);
    	auto rc = reverse(r);
    	if(lc)
    		lc->left = root;//子节点的left指向父节点
    	if(rc)
    		rc->left = root;
    	return root;
    }
};

0 ms 9 MB

  • 上面做法遍历了2次树,更简单的做法,按照树的高度(2侧子树的最大高度 + 1自己)来分组
class Solution {
    vector<vector<int>> ans;
public:
    vector<vector<int>> findLeaves(TreeNode* root) {
        dfs(root);
        return ans;
    }
    int dfs(TreeNode* root)
    {
        if(!root) return -1;
        int hl = dfs(root->left);
        int hr = dfs(root->right);
        int hcur = max(hl, hr) + 1;
        if(ans.size() <= hcur)
            ans.push_back({});
        ans[hcur].push_back(root->val);
        return hcur;
    }
};

4 ms 9.1 MB


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!
Michael阿明

  • 42
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Michael阿明

如果可以,请点赞留言支持我哦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值