二叉树遍历进阶

本文介绍了如何使用二叉树的垂直遍历解决力扣上的两道题目,分别是987.二叉树的垂序遍历和1302.层数最深叶子节点的和。通过递归深度优先搜索(DFS)和哈希映射记录节点信息,对节点按特定顺序排序,高效地找到目标答案。文章强调了哈希表在算法中的灵活运用和排序技巧。
摘要由CSDN通过智能技术生成

声明:本博客记录的题目全部来自于力扣,对这些题目进行整理的人为花花酱以及他的个人网站,本博客主要用来记录自己的算法学习的笔记。

二叉树的垂序遍历

本题来自于力扣987. 二叉树的垂序遍历
根据题目意思,我们可以先整个遍历这个树,并且对这个树进行标记(col, row, val),并使用这个三个值进行排序,col为第一排序,row为第二排序,val为第三排序。
使用dfs进行遍历,并标记,使用map存储标记
本题的题解主要参考宫水三叶的题解,点击连接有更多题解思路提供
题解

class Solution {
    
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        Map<TreeNode,int []> map = new HashMap();
        List<List<Integer>> result = new ArrayList();

        map.put(root, new int[]{0,0,root.val});

        recursion(root, map);

        List<int[]> list = new ArrayList<>(map.values());
        Collections.sort(list, (a, b)->{
            if (a[0] != b[0]) return a[0] - b[0];
            if (a[1] != b[1]) return a[1] - b[1];
            return a[2] - b[2];
        });

        int n = list.size();

        for (int i = 0; i < n; ) {
            int j = i;
            List<Integer> tmp = new ArrayList<>();
            while (j < n && list.get(j)[0] == list.get(i)[0]){
            	tmp.add(list.get(j++)[2]);
            }
            result.add(tmp);
            i = j;
        }
        return result;
    }

    public void recursion(TreeNode root, Map<TreeNode, int[]> map){
        if(root == null){
            return ;
        }

        int[] info = map.get(root);
        int row = info[1], col = info[0], val = info[2];
        if(root.left != null){
            map.put(root.left, new int[]{col - 1, row + 1, root.left.val});
            recursion(root.left, map);
        }

        if(root.right != null){
            map.put(root.right, new int[]{col + 1, row + 1, root.right.val});
            recursion(root.right, map);
        }
    }
}

使用dfs遍历的原理基本上和基础遍历差不多,这里主要学习到的是哈希表的灵活应用
以及接下来记录的排序使用

 Collections.sort(list, (a, b)->{
            if (a[0] != b[0]) return a[0] - b[0];
            if (a[1] != b[1]) return a[1] - b[1];
            return a[2] - b[2];
        });

这个代码里面构造的是一个比较器:
如果第一个值减去第二个值,则是降序排序
如果第二值减去第一个值,则是升序排序
靠前的就是第一排序,第二排序,和第三排序

层数最深叶子节点的和

本题来自于力扣1302. 层数最深叶子节点的和
根据上述题目的学习,我们很快就能根据上面的风格写出如下代码

class Solution {
    public int deepestLeavesSum(TreeNode root) {
        Map<TreeNode, int[]> map = new HashMap();
        map.put(root, new int[]{0,root.val});//row和val

        dfs(root,map);
        List<int[]> list = new ArrayList<>(map.values());
        Collections.sort(list, (a, b)->{
            if (a[0] != b[0]) return b[0] - a[0];
            return b[1] - a[1];
        });
        int maxRow = list.get(0)[0];
        int ans = 0;
        int i = 0;
        while(list.get(i)[0] == maxRow){
            ans = ans + list.get(i)[1];
            i++;
        }

        return ans;
    }

    public void dfs(TreeNode root, Map<TreeNode, int[]> map){
        if(root == null){
            return;
        }

        int[] info = map.get(root);
        int row = info[0], val = info[1];
        if(root.left != null){
            map.put(root.left, new int[]{row + 1, root.left.val});
            dfs(root.left, map);
        }
        if(root.right != null){
            map.put(root.right, new int[]{row + 1, root.right.val});
            dfs(root.right, map);
        }
    }
}

显然这个代码很长,而且执行效率很低,这个时候我们可以思考是否可以在遍历的时候就把最深的节点找出并得出结果呢?

改变思路就有了以下代码,很多事情同时做,同时比较

class Solution {
    int deepRow;
    int deepRowSum;
    public int deepestLeavesSum(TreeNode root) {
        dfs(root,0);
        return deepRowSum;
    }

    public void dfs(TreeNode root, int row){
        if(root == null){
            return;
        }

        if(row > deepRow){
            deepRow = row;
            deepRowSum = 0;
        }
        
        if(row == deepRow){
            deepRowSum = deepRowSum + root.val;
        }

        dfs(root.left, row + 1);
        dfs(root.right, row + 1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值