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