思路
广度优先遍历。
维护一个 Queue,首先将根节点加入到 Queue 中。
维护两个计数器,numsOfThisLevel:记录本层的节点数, numsOfSonLevel:记录下一层的节点数。
维护一个标志位 needReverse,初始置为false。
维护一个外层 List<List>,和一个 内层的 List。
循环,当 Queue 不为空时:
- 取出一个节点,把它的 val 加入内层List。
- 当它的左节点不为空时,将它的左节点加入到队列中。并且下层的节点数 + 1;
- 当它的右节点不为空时,将它的右节点加入到队列中。并且下层的节点数 + 1;
- 判断内层 List 的大小是否已经等于了本层节点数。如果等于,判断是需要翻转内部 List。
那么就把 内层 List加入到外层 List 中,然后新建一个内层 List。
并且将两层的计数器,都下移一层(numsOfThisLevel = numsOfSonLevel; numsOfSonLevel = 0)。
将标志位 needReverse 置为 !needReverse.
复杂度分析
假设树有 n 个节点。
- 时间复杂度O(n),遍历整棵树。
- 空间复杂度O(n),空间复杂度取决二叉树的节点数。
代码
public static List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
if (root == null) return ans;
Queue<TreeNode> nodes = new LinkedList<>();
List<Integer> nums = new ArrayList<>();
nodes.offer(root);
int numsOfThisLevel = 1;
int numsOfSonLevel = 0;
boolean needReverse = false;
while (!nodes.isEmpty()) {
TreeNode node = nodes.poll();
nums.add(node.val);
if (node.left != null) {
nodes.offer(node.left);
numsOfSonLevel++;
}
if (node.right != null) {
nodes.offer(node.right);
numsOfSonLevel++;
}
if (nums.size() == numsOfThisLevel) {
if (needReverse) {
Collections.reverse(nums);
}
ans.add(nums);
nums = new ArrayList<>();
numsOfThisLevel = numsOfSonLevel;
numsOfSonLevel = 0;
needReverse = !needReverse;
}
}
return ans;
}