leetCode987 二叉树的垂序遍历(hard)

好久没更新了,因为刚换了工作,比较忙。这次更新就由这道表面hard,实则medium的题目开始吧,同时希望自己的生活工作哪怕遇到hard,但也能积极面对,最后发现其实也就那回事!

审题:

给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。

对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1) 。树的根结点位于 (0, 0) 。

二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。

返回二叉树的 垂序遍历 序列。

来源:力扣(LeetCode)
读完题目,应该还是很明白的,就是从左到右,从上到下,相同位置则从小到大,来对二叉树进行遍历

思考:

我们可以记录每个节点的位置信息,比如可以定义一个int[] a, a[0]记录x轴坐标,a[1]记录y轴坐标,a[2]记录节点的值,然后用一个list去储存这个a,最后对list按照上面的要求来进行排序即可,详细见代码和注释:

        public List<List<Integer>> verticalTraversal(TreeNode root) {
            List<int[]> list = new ArrayList<>();
            listNode(root, list, null, true);
            // 从左到右,从上到下,相同位置则从小到大进行排序
            list.sort((o1, o2) -> {
                if (o1[0] != o2[0]) {
                    return o1[0] - o2[0];
                } else if (o1[1] != o2[1]) {
                    return o1[1] - o2[1];
                } else return o1[2] - o2[2];
            });

            List<List<Integer>> re = new ArrayList<>();
            List<Integer> ll = new ArrayList<>();
            // 进行分组,同一个x坐标则在一个组
            for (int i = 0; i < list.size() - 1; i++) {
                ll.add(list.get(i)[2]);
                if (list.get(i)[0] != list.get(i + 1)[0]) {
                    re.add(ll);
                    ll = new ArrayList<>();
                }
            }
            // 处理一下最右边的一个节点
            ll.add(list.get(list.size() - 1)[2]);
            re.add(ll);
            return re;
        }


        /**
         * 进行递归先序遍历,为了通过父节点信息对子节点位置进行计算
         * 定义一个int[3] 分别存x y val
         *
         * @param fa 父亲节点的位置信息
         * @param b  左节点true 右节点false
         */
        void listNode(TreeNode node, List<int[]> list, int[] fa, boolean b) {
            if (node == null) return;
            int[] a = new int[3];
            // fa为null 的时候说明是父亲节点,那么x=0,y=0,默认值
            if (fa != null) {
                if (b) {
                    // 左节点x向左进行偏移一位
                    a[0] = fa[0] - 1;
                } else {
                    // 右节点x向右进行偏移一位
                    a[0] = fa[0] + 1;
                }
                // 无论左右节点,y都要+1
                a[1] = fa[1] + 1;
            }
            //保存节点值
            a[2] = node.val;
            list.add(a);
            listNode(node.left, list, a, true);
            listNode(node.right, list, a, false);
        }

总结:

这道题思路还是很清晰的,一定要熟练掌握二叉树的遍历,尤其是进行遍历的时候,保存一些状态值。

原文地址:https://www.cnblogs.com/junlancer/p/15085818.html