[leetcode] 特定深度节点链表

  给定一颗二叉树,设计一个算法,创建含有某一深度上所有节点的链表(比如,若一颗树的深度为 D,则会创建出 D 个链表)。返回一个包含所有深度的链表的数组。

  这道题使用层次遍历对二叉树进行遍历,在遍历过程中确定节点属于哪一层,将同一层的节点放在同一个链表下即可。

  在做这道题的时候,我在处理节点层级这个点上处理的不太好。一开始,我构建一个类来存储节点的层次信息,这个类中包含树节点和该节点的层级。

class DepthTreeNode {
    TreeNode node;
    int depth; // 深度

    public DepthTreeNode(TreeNode node, int depth) {
        this.node = node;
        this.depth = depth;
    }
}

 

   这种方式都极大影响了存储和运行时间,在进行层次遍历时,需要为每一个节点创建一个 DepthTreeNode ,然后再将节点存储层次遍历所用到的辅助结构队列当中,从队列中取出节点进行操作的时候,同样还要取出 DepthTreeNode 中的 TreeNode ,相当于包了层盒子只为了存储层次信息,造成巨大的浪费。

  后来看了一个题解,使用一个变量(size)记录正在处理的层一共有多少个节点。根据层次遍历的实现特点,每次处理一个节点时,会加入它的子节点。当上一层(n-1)的节点全部处理完之后,队列中剩余的节点都为同一层(n)的节点,也就是说,此时队列中的节点数量就是第 n 层节点的个数(size),那么使用 size 来控制接下来处理的节点的个数就能保证处理的都是第 n 层的节点了。

 

  还有两个细节需要注意。

  1. 含有所有深度的链表的数组的长度怎么确定?

  你可以先对二叉树进行遍历,获得二叉树的深度,然后确定数组的长度。

  或者一开始可以并不考虑长度问题,使用 ArrayList 进行存储,最后再使用数组进行存储。

  2. 同一深度的链表在处理时要不要再首部添加一个辅助的空的 ListNode?

  

  这是题解里面的做法,其实不添加也可以。添加的话在代码实现方面,处理节点层级上会更有条理。当换到新一层时,可以集中于处理链表的转换问题,当遇到同一层的新节点时,可以集中于处理节点连接的问题。

  代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */


class Solution {
    public ListNode[] listOfDepth(TreeNode tree) {
         Queue<TreeNode> queue = new LinkedList<>(); // 辅助队列
        List<ListNode> list = new ArrayList<>(); // 存储返回结果

        ListNode start = new ListNode(0); // 返回结果中每一层元素前,使用 start 作为一个空元素来定位
        ListNode tail = null; // 记录返回结果中加入的最后一个元素
        int size = 1;// 上一层仍然需要处理的元素个数
        // 数据预处理
        list.add(start);
        tail = start;

        queue.add(tree);
        while (!queue.isEmpty()) {
            if (size > 0) { // 上一层仍然有未处理的元素
                size--;
                TreeNode curNode = queue.poll();
                tail.next = new ListNode(curNode.val);
                tail = tail.next;
                if (curNode.left != null)
                    queue.add(curNode.left);
                if (curNode.right != null)
                    queue.add(curNode.right);
            } else { // 上一层的元素全部处理完毕
                size = queue.size();
                start = new ListNode(0);
                list.add(start);
                tail = start;
            }
        }
        ListNode[] res = new ListNode[list.size()];
        int j = 0;
        for (ListNode node : list) {
            res[j++] = node.next;
        }
        return res;
    }
}

 

posted @ 2021-01-26 16:38  葡萄籽pp  阅读(128)  评论(0编辑  收藏  举报