LeetCode 987. 二叉树的垂序遍历

截止到目前我已经写了 600多道算法题,其中部分已经整理成了pdf文档,目前总共有1000多页(并且还会不断的增加),大家可以免费下载
下载链接https://pan.baidu.com/s/1hjwK0ZeRxYGB8lIkbKuQgQ
提取码:6666

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这题虽然是hard,但其实没有什么难度,做这题我最先想到的就是BFS遍历,如果当前节点是第m列,那么他的左子节点就是第m-1列,右子节点就是m+1

在这里插入图片描述

所以我们可以从上到下一层一层的遍历,使用一个map来存储,map的key存储的是第几列,value是那个列的集合。辛辛苦苦写完之后发现运行不通过(代码放在了下面,有兴趣的可以看下),这是因为题中有这样一句话,如果同行同列上有多个结点,则按结点的值从小到大进行排序。也就是说如果两个节点位置重合了还要按照大小进行排序。


所以这题我们只能按照常规方式来解决,就是先记录下每个节点的值和坐标,最后再把他们按照同一列的顺序放到集合中,关于二叉树的遍历有多种,我们之前也介绍过一些

373,数据结构-6,树

488,二叉树的Morris中序和前序遍历

来看下代码

public List<List<Integer>> verticalTraversal(TreeNode root) {
    //list集合中的元素是一个数组,每个数组的长度都是3,第1个值表示
    //节点的值,第2个和第3个值表示节点的横坐标和竖坐标
    List<int[]> mList = new ArrayList<>();
    //计算所有节点的值和坐标,根节点的坐标是(0,0)
    dfs(root, 0, 0, mList);
    //排序,排序的原则是先排左边一列,所以首先比较的是数组的第3个值(
    //纵坐标),然后每一列从上到下也就是数组的第2个值(横坐标),如果
    //前面两个值是一样的说明他们的坐标重合了,要按值从大到小排序
    Collections.sort(mList, (arr1, arr2) -> {
        //先按照纵坐标排序
        if (arr1[2] != arr2[2])
            return arr1[2] - arr2[2];
        if (arr1[1] != arr2[1])
            return arr1[1] - arr2[1];
        //如果坐标一样,再按照值排序
        return arr1[0] - arr2[0];
    });

    //把节点的值进行垂序分类
    List<List<Integer>> res = new ArrayList<>();
    res.add(new ArrayList<>());
    //因为上面排序了,所以这里首先遍历的就是最左边一列的值,
    //然后是第二列……
    for (int i = 0; i < mList.size(); i++) {
        //取出数组(包含当前节点的值和坐标)
        int[] arr = mList.get(i);
        //当前节点的值
        int value = arr[0];
        //如果当前节点和前一个节点不在同一列,说明到下一
        //列了,需要初始化下一列的集合
        if (i > 0 && arr[2] != mList.get(i - 1)[2])
            res.add(new ArrayList<>());
        //把当前节点的值添加到当前列中
        res.get(res.size() - 1).add(value);
    }
    return res;
}

private void dfs(TreeNode node, int i, int j, List<int[]> mList) {
    if (node == null)
        return;
    //把当前节点的值和坐标加入到集合中,当前节点的坐标是(i,j)
    mList.add(new int[]{node.val, i, j});
    //遍历左子节点
    dfs(node.left, i + 1, j - 1, mList);
    //遍历右子节点
    dfs(node.right, i + 1, j + 1, mList);
}
  • 75
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

数据结构和算法

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值