层序遍历
我们是用队列来保存元素。同时记录队列的大小,用来表示一层有几个节点。从而实现分层进行操作
遍历每一层(每一层遍历size次)的同时,把它的左右孩子都入队(插入队尾)(如果有的话)。
- java代码
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> queue = new ArrayDeque<>(); //初始化队列
if(root == null) return res;
queue.push(root);
while(!queue.isEmpty()) {
List<Integer> floor = new ArrayList<>(); //存放每一层的结果
int len = queue.size();
for(int i = 0; i < len; i++) { //对每一层进行操作
TreeNode tmp = queue.pop(); //取出队头,加入结果数组同时将左右孩子入队(插入队尾用offer)
floor.add(tmp.val);
if(tmp.left != null) queue.offer(tmp.left);
if(tmp.right != null) queue.offer(tmp.right);
}
//每一层遍历完后添加一次floor数组
res.add(floor);
}
return res;
}
}
107.二叉树的层次遍历 II
直接Collections.reverse(res);就行
199.二叉树的右视图
题目是一维数组,在每层的for循环里加一个判断,if(i == len-1) 才加到答案数组里。
637.二叉树的层平均值
每层用sum累加,在每层的for循环里加一个判断,if(i == len-1) 才把sum/len加到答案数组里。
429.N叉树的层序遍历
注意要改变添加每层的孩子节点的逻辑!
List<Node> children = tmp.children; //先把孩子结点list取出来
if (children == null || children.size() == 0) { //如果没有孩子了就跳过这次循环
continue;
}
for (Node child : children) { //遍历孩子结点list 不为空就加到队列里
if (child != null) {
queue.offer(child);
}
}
515.在每个树行中找最大值
在每次进while(相当于处理下一层)的时候,初始化max=Integer.MIN_VALUE
,然后在for循环里max=Math.max(max,node.val)
116.填充每个节点的下一个右侧节点指针
在单层遍历的时候记录一下本层的头部节点(先取出,然后把左右孩子入队一次),然后在遍历的时候让前一个节点指向本节点就行(size-1次)
104.二叉树的最大深度
遍历每一层的同时depth++
111.二叉树的最小深度
只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点。只要遇到了就直接返回depth即可
226. 翻转二叉树
想要翻转它,其实把每一个节点的左右孩子交换一下就可以了。
那我们采用什么方式遍历呢?前 后 层序都可以,唯独中序不行!(其实也可以,只要修改一下right成left就行)中序反转左子树后,回到根节点,此时的右子树实际上是原来的左子树!
递归三部曲
- 确定递归函数的参数和返回值
参数就是要传入节点的指针,不需要返回值
void reverse(TreeNode root)
- 确定终止条件
当前节点为空的时候,就返回
if (root == NULL) return root;
- 确定单层递归的逻辑
先前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
注意swap函数要写成swap(TreeNode root)!不能直接交换left和right
- java代码(前序)
class Solution {
public void reverse(TreeNode root) {
if(root == null) return;
swap(root);
reverse(root.left);
reverse(root.right);
}
public void swap(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
public TreeNode invertTree(TreeNode root) {
reverse(root);
return root;
}
}
101.对称二叉树
我们判断是否对称,实际是判断根节点的左子树和右子树是否可以相互翻转。同为内侧节点两两比较,同为外侧节点两两比较。
确定遍历顺序
这题==只能用后序!==因为我们要不断收集左右孩子的信息,然后返回给上一个节点(上一层)。我才能知道左节点为根的树和 右节点为根的树 是否是相互反转的。
后序:左 右 中
代码实现
- 确定递归函数的返回值和参数
bool compare(TreeNode left, TreeNode right)
- 确定终止条件
左为空 && 右不为空 false
左不为空 && 右为空 false
左为空 && 右为空 true
左右都不为空 && 值不相等 false
左右都不为空 && 值相等 true
- 单次递归逻辑
分别判断左右侧 孩子是否都对称相等!(这个结果最终会传回来,一直传到根节点)
boolean outside = compare(left.left, right.right); //左
boolean inside = compare(left.right, right.left); //右
boolean result = inside && outside; //中
- java代码
class Solution {
//后序遍历 左右中
public boolean compare(TreeNode left, TreeNode right) {
if(left == null && right != null) return false;
else if(left != null && right == null) return false;
else if (left == null && right == null) return true;
else if(left.val != right.val) return false;
boolean outside = compare(left.left, right.right); //左
boolean inside = compare(left.right, right.left); //左
boolean result = outside && inside; //中
return result;
}
public boolean isSymmetric(TreeNode root) {
return compare(root.left,root.right);
}
}