[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; } }