【问题标题】:Vertical Order Traversal of a Binary Tree using dfs and Map使用 dfs 和 Map 对二叉树进行垂直顺序遍历
【发布时间】:2021-02-16 19:36:09
【问题描述】:

我正在尝试对二叉树进行垂直顺序遍历,这个问题:https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/

我的方法:我对树中的每个节点进行深度优先搜索,其中根为 0。左边的任何内容都是当前根 - 1,右边的任何内容都是当前root + 1。我还有一个 HashMap,其中键是节点的值(具有相同位置匹配的节点),值是具有相同位置的所有 TreeNode 的链表(键值)。

当我打印出 HashMap 的值时,我看到它有正确的元素组合在一起。

问题是当我返回最终列表时,整数列表的顺序不正确,应该从最大的负数到最大的正数 - 相反,与根相同位置的元素被打印出来第一的。我认为这是因为我不能使用负数作为 HashMap 的键——但我想不出办法。

例如:

如果输入树是:

程序应该返回:[[9], [3,15], [20], [7]]

然而,我的回报:[[3,15], [9], [20], [7]]

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        /*dfs getting value of node & adding it to list*/
        List<List<Integer>> list = new ArrayList<>();
        
        Map<Integer, List<Integer>> map = new HashMap<>();
        
        if(root == null) {
            return list;
        }
        
        dfs(root, map, 0);
        
        for(Map.Entry<Integer, List<Integer>> m : map.entrySet()) {
            List<Integer> temp = new ArrayList<>();
            for(int i : m.getValue()) {
                temp.add(i);
            }
            list.add(temp);
        }
        
        return list;
    }
    
    public static void dfs(TreeNode root,  Map<Integer, List<Integer>> map, int curVal) {
        if(root == null) {
            return;
        }
        
        // System.out.println("root val = " + root.val);
        // System.out.println("curVal = " + curVal);
        
        if(map.containsKey(curVal)) {
            List temp = map.get(curVal);
            temp.add(root.val);
            map.put(curVal, temp);
        }
        else {
            List<Integer> tempList = new ArrayList<>();
            tempList.add(root.val);
            map.put(curVal, tempList);
        }
        
        dfs(root.left, map, curVal - 1);
        dfs(root.right, map, curVal + 1);
    }
}

【问题讨论】:

    标签: java tree binary-tree tree-traversal


    【解决方案1】:

    否定键没有问题,但缺少几件事。

    • HashMap 不维护任何顺序,即使这样做了,您也会以深度优先顺序将元素添加到 HashMap,这意味着首先添加根。所以在你的输出中你没有得到预期的顺序是很正常的。

      您应该改为按其键值的顺序迭代地图。

    • 当多个值被添加到同一个映射条目时(因为键是相同的),您也在按照访问它们的顺序添加它们。但是这个顺序并不能保证是所需的顺序:深度优先迭代将在树中上下移动,因此不能保证您会先处理上层节点,再处理下层节点。如果你想要这样,你需要一个广度优先。或者,您可以将 y 坐标(级别)作为参数传递。

    • 当两个节点具有相同的 x 和 y 坐标时,它们的值应按升序报告。你对此没有任何规定。如果您坚持深度优先,那么在地图条目中,您将需要另一个以 y 坐标为键的地图。然后,当您发现当前 y 坐标已经有一个条目时,您应该确保以正确的顺序添加当前节点的值。请注意,这会为您的数据结构添加一个嵌套级别。最好先添加值而不进行排序,然后在算法的最后阶段遍历完整的数据结构并对所有这些小子数组进行排序。

    【讨论】:

    • 我不确定我是否理解最后一点,即使两个点共享(x,y)坐标,它们也会映射到HashMap中的不同键。您认为我应该如何更改代码以实现此逻辑-我是否应该为每个 TreeNode 创建一个具有 (x,y) 坐标的子类,然后按其键对 HashMap 进行排序并根据其 x 和 y 在每个值处对每个数组进行排序坐标?
    • 节点值列表的散列图(由 x 键控)的散列图(由 x 键控)。需要对节点值的小列表进行排序。
    猜你喜欢
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多