102. 二叉树的层序遍历
一个简单的二叉树示例:
3
/ \
9 20
/ \
15 7
输出的结果应该是:
[
[3],
[9,20],
[15,7]
]
算法步骤如下:
代码如下:
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> queue = new ArrayDeque<>();
if (root != null) {
queue.add(root);
}
while(!queue.isEmpty()){
List<Integer> level = new ArrayList<>();
int len = queue.size();
for(int i = 0; i<len; i++){
TreeNode node = queue.poll();
level.add(node.val);
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
}
res.add(level);
}
return res;
}
}
107. 二叉树的层序遍历 II
一个简单的二叉树示例:
3
/ \
9 20
/ \
15 7
输出的结果应该是:
[
[15,7],
[9,20],
[3]
]
思路:
其实跟上面那题一样,我们只需要在添加进list的时候,添加到最前面即可,可以使用list.add(index,val)的方法,在索引为0的位置添加对应的值。
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> queue = new ArrayDeque<>();
if(root != null){
queue.add(root);
}
while(!queue.isEmpty()){
List<Integer> level = new ArrayList<>();
int len = queue.size();
for(int i=0; i<len; i++){
TreeNode node = queue.poll();
level.add(node.val);
TreeNode left = node.left, right = node.right;
if(left != null){
queue.add(left);
}
if(right != null){
queue.add(right);
}
}
res.add(0, level);
}
return res;
}
}
leetcode 103. 二叉树的锯齿形层序遍历
一个简单的二叉树示例:
3
/ \
9 20
/ \
15 7
输出的结果应该是:
[
[3],
[20,9],
[15,76]
]
思路:
三个地方
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if(root == null){
return res;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
Boolean isOrderLeft = true;
while(!queue.isEmpty()){
Deque<Integer> level = new LinkedList<Integer>();
int len = queue.size();
for(int i=0; i<len; i++){
TreeNode node = queue.poll();
if(isOrderLeft){
level.offerLast(node.val);
}else{
level.offerFirst(node.val);
}
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
res.add(new LinkedList<Integer>(level));
isOrderLeft = !isOrderLeft;
}
return res;
}
}
leeetcode 429. N 叉树的层序遍历
这种方法跟前面的大差不差,就是主要是deque的处理
代码解释:
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<>();
Deque<Node> q = new ArrayDeque<>();
if(root != null){
q.add(root);
}
while(!q.isEmpty()){
Deque<Node> next = new ArrayDeque<>();
List<Integer> nd = new ArrayList<>();
while(!q.isEmpty()){
Node cur = q.pollFirst();
nd.add(cur.val);
for(Node chd : cur.children){
if(chd != null){
next.add(chd);
}
}
}
q = next;
res.add(nd);
}
return res;
}
}
使用广度优先搜索(BFS)算法实现N叉树的层次遍历的时间复杂度和空间复杂度如下:
思路:
使用递归的方式进行深度优先搜索。在每次递归调用时,我们传入当前节点、当前层级和结果列表。如果当前层级超过了结果列表的大小,我们会在结果列表中添加一个新的空列表,用于存储当前层级的节点值。
然后,我们将当前节点的值添加到对应层级的列表中。接下来,我们对当前节点的所有子节点进行递归调用,将层级加一,并继续向下搜索。
最终,函数返回时,我们得到了一个按层级分组的节点值列表,即N叉树的层次遍历结果。
使用深度优先搜索(DFS)算法实现N叉树的层次遍历可以通过以下步骤来实现:
创建一个空的结果列表 res
,用于存储最终的层次遍历结果。
如果根节点 root
不为空,调用辅助函数 dfs(root, 0, res)
进行递归遍历。
在 dfs
函数中,传入当前节点 node
、当前层级 level
和结果列表 res
。
如果当前层级 level
大于等于结果列表 res
的大小,说明当前层级还没有被访问过,需要在结果列表中添加一个新的空列表。
将当前节点 node
的值添加到结果列表 res
中对应层级的列表中。
遍历当前节点的所有子节点 child
,如果子节点不为空,则进行递归调用 dfs(child, level + 1, res)
,并将层级加一。
最终,函数返回时,我们得到了一个按层级分组的节点值列表,即N叉树的层次遍历结果。
下面是使用深度优先搜索算法实现N叉树层次遍历的Java代码示例:
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<>();
if (root != null) {
dfs(root, 0, res);
}
return res;
}
private void dfs(Node node, int level, List<List<Integer>> res) {
if (level >= res.size()) {
res.add(new ArrayList<>());
}
res.get(level).add(node.val);
for (Node child : node.children) {
if (child != null) {
dfs(child, level + 1, res);
}
}
}
}
对于给定的N叉树,使用深度优先搜索(DFS)算法实现层次遍历的空间复杂度和时间复杂度如下:
leetcode 515. 在每个树行中找最大值
这题就比较简单啦~
其实就是层次遍历的变形,遍历节点的同时去判断值,那就需要拿一个值去获取,即可~
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> q = new ArrayDeque<>();
if(root != null){
q.addLast(root);
}
while(!q.isEmpty()){
int len = q.size();
int levelNumMax = Integer.MIN_VALUE;
for(int i=0; i<len; i++){
TreeNode node = q.poll();
levelNumMax = Math.max(node.val, levelNumMax);
if(node.left != null) q.addLast(node.left);
if(node.right != null) q.addLast(node.right);
}
res.add(levelNumMax);
}
return res;
}
}
leetcode 637. 二叉树的层平均值
这题跟上一题一样的,只是把判断最大值改成计算总和,最后再添加到列表里,所以没什么好说的
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new ArrayList<>();
Deque<TreeNode> q = new ArrayDeque<>();
if(root != null){
q.addLast(root);
}
while(!q.isEmpty()){
int len = q.size();
double sum = 0;
for(int i=0; i < len; i++){
TreeNode node = q.poll();
sum += node.val;
if(node.left != null) q.addLast(node.left);
if(node.right != null) q.addLast(node.right);
}
res.add(sum/len);
}
return res;
}
}
leetcode 199. 二叉树的右视图
这题也很简单,主要的难点是将节点放入队列后,怎样让弹出的节点是最右边那个
我直接用双端队列,比较简单,偷懒了~~不过,好像区别不大。
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> q = new ArrayDeque<>();
if (root != null) {
q.addLast(root);
}
while (!q.isEmpty()) {
int len = q.size();
int rightNode = 0;
for (int i = 0; i < len; i++) {
TreeNode node = q.poll();
rightNode = node.val; // 每一层的最右节点值更新为当前节点的值
if (node.left != null) {
q.addLast(node.left); // 将下一层的左子节点加入队列
}
if (node.right != null) {
q.addLast(node.right); // 将下一层的右子节点加入队列
}
}
res.add(rightNode); // 将每一层的最右节点值添加到结果列表
}
return res;
}
}
注意:
在每次遍历的过程中,通过不断取出队列中的节点,并更新rightNode
变量为当前节点的值,可以保证q.poll()
取出的是每一层的最右节点。
leetcode LCR 045. 找树左下角的值
这题也差不多,也是在广度优先搜索的情况下多一点要求
这里找到最左的节点,也就是最下面那一层,遍历的时候,第一次遍历的第一个结点,那么也就是内嵌循环的第一次就是最左节点
class Solution {
public int findBottomLeftValue(TreeNode root) {
Deque<TreeNode> q = new ArrayDeque<>();
int leftValue = 0;
if (root != null) {
q.add(root); // 将根节点添加到队列中
}
while (!q.isEmpty()) {
int len = q.size();
for (int i = 0; i < len; i++) {
TreeNode node = q.poll();
if (i == 0) {
leftValue = node.val;
}
if (node.left != null) {
q.add(node.left);
}
if (node.right != null) {
q.add(node.right);
}
}
}
return leftValue;
}
}
搞定~~