https://leetcode.cn/problems/binary-tree-level-order-traversal/
BFS已经写熟了,由于是输出List>而不是直接打印,所以可以用dfs三个顺序遍历都可以,找到所在层,在该层所在list里添加。
class Solution {
public List> levelOrder(TreeNode root) {
List> result = new ArrayList<>();
dfs(root, result, 0);
return result;
}
private void dfs(TreeNode root, List> result, int depth) {
if (root == null) return;
if (result.size() < depth + 1) result.add(new ArrayList<>()); // bug if(result.get(depth) == null) 会out of bound
result.get(depth).add(root.val);
dfs(root.left, result, depth + 1);
dfs(root.right, result, depth + 1);
}
}
https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/
关键点是 List用LinkedList,每个新层放在index=0的头部,容易出bug的地方在dfs方法里,计算所在node要放在哪个list需要从后向前(即从root向下)数index.
class Solution { // dfs
public List> levelOrderBottom(TreeNode root) {
List> result = new LinkedList<>();
dfs(root, result, 0);
return result;
}
private void dfs(TreeNode root, List> result, int depth) {
if (root == null) return;
if (result.size() < depth + 1) {
result.add(0, new ArrayList<>()); //改为在队头插入新list
}
dfs(root.left, result, depth + 1);
dfs(root.right, result, depth + 1);
result.get(result.size() - 1 - depth).add(root.val); // 容易出bug, 这个size是当前所知的最大数高,depth是已知的只等于从队尾开始计数的list数目,从前数的index会变
// .add这行的位置可以往前在dfs前或者两dfs中间都可以
}
}
class Solution { // bfs
public List> levelOrderBottom(TreeNode root) {
List> result = new LinkedList<>();
Queue queue = new LinkedList<>();
if (root != null) queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
result.add(0, new ArrayList<>());
while (size-- > 0) {
TreeNode cur = queue.poll();
result.get(0).add(cur.val);
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
}
}
return result;
}
}
https://leetcode.cn/problems/binary-tree-right-side-view/description/
可以BFS,当确认是当层最后一个节点时输出;这里用中右左的pre-order dfs,只有是前序遍历时,填结果的顺序才能保证是从上层到下层的顺序,因为后序遍历填出来是从下到上,中序遍历在depth上的顺序是乱的。
class Solution {
public List rightSideView(TreeNode root) {
List result = new ArrayList<>();
dfs(root, result, 0);
return result;
}
private void dfs(TreeNode root, List result, int depth) { //按中右左进行前序遍历
if (root == null) return;
if (result.size() < depth + 1) {
result.add(root.val);
}
dfs(root.right, result, depth + 1);
dfs(root.left, result, depth + 1);
}
}
https://leetcode.cn/problems/average-of-levels-in-binary-tree/description/
BFS更直接。
class Solution {
public List averageOfLevels(TreeNode root) {
Queue queue = new ArrayDeque<>();
List result = new ArrayList<>();
if (root != null) queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
double sum = 0.0;
for (int i = 0; i < size; i++) {
TreeNode cur = queue.poll();
sum += cur.val;
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
}
result.add(sum / size);
}
return result;
}
}
https://leetcode.cn/problems/n-ary-tree-level-order-traversal/description/
BFS比较方便,DFS也可以做,和102题一样。
class Solution {
public List> levelOrder(Node root) {
List> result = new ArrayList<>();
Queue queue = new ArrayDeque<>();
if (root != null) queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
result.add(new ArrayList<>());
while (size-- > 0) {
Node cur = queue.poll();
result.get(result.size() - 1).add(cur.val);
for (Node child : cur.children) {
queue.offer(child);
}
}
}
return result;
}
}
https://leetcode.cn/problems/find-largest-value-in-each-tree-row/ BFS更直观,这里写DFS,DFS里更新最大可前中后序,但是在line 9在list里加入该层第一个点作为place holder需要在前序中,否则会out of bound.
class Solution {
public List largestValues(TreeNode root) {
List result = new ArrayList<>();
dfs(root, result, 0);
return result;
}
private void dfs(TreeNode root, List result, int depth) {
if (root == null) return;
if (result.size() < depth + 1) result.add(root.val); //bug 一定要先把空开出来,不然dfs在前会out of bound
dfs(root.left, result, depth + 1);
if (root.val > result.get(depth)) result.set(depth, root.val); //可以在第一个dfs前也可以在第二个dfs后
dfs(root.right, result, depth + 1);
}
}
https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/
如果不是该层第一个,则让pre.next指向它。这题DFS不方便。
class Solution {
public Node connect(Node root) {
if (root == null) return root;
Queue queue = new ArrayDeque<>();
Node pre = root;
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Node cur = queue.poll();
if (i != 0) pre.next = cur;
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
pre = cur;
}
}
return root;
}
}
https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/description/
和116完全一样,116是complet tree这里是general tree.
https://leetcode.cn/problems/maximum-depth-of-binary-tree/
可以BFS记录一个depth每层++,这里用DFS后序遍历。
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
https://leetcode.cn/problems/minimum-depth-of-binary-tree/description/
BFS做法,遇到第一个叶子返回depth.
class Solution {
public int minDepth(TreeNode root) {
Queue queue = new ArrayDeque<>();
int depth = 0;
if (root != null) queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
depth++;
while (size-- > 0) {
TreeNode cur = queue.poll();
if (cur.left == null && cur.right == null) return depth;
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
}
}
return depth;
}
}
DFS 不能直接写
{ if (root == null) return 0;
return Math.min(minLeft, minRight) + 1; }
同时为null时0都有效,其他时候为0时无效忽略改为MAX。
class Solution {
public int minDepth(TreeNode root) {
if (root == null) return 0;
int minLeft = minDepth(root.left);
int minRight = minDepth(root.right);
if (minLeft == 0 && minRight != 0) minLeft = Integer.MAX_VALUE;
if (minRight == 0 && minLeft != 0) minRight = Integer.MAX_VALUE;
return Math.min(minLeft, minRight) + 1;
}
}
https://leetcode.cn/problems/invert-binary-tree/
BFS可以先翻孩子再把孩子入队可以,孩子入队再翻孩子也可以,DFS里前序和后序都可以, 中序也可以但第二个孩子要翻原来的右孩子,也就是新左孩子;卡哥也用了用栈的iterative的遍历方法这里没写。
class Solution { // BFS
public TreeNode invertTree(TreeNode root) {
Queue queue = new ArrayDeque<>();
if (root != null) queue.offer(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
TreeNode temp = cur.left;
cur.left = cur.right;
cur.right = temp;
if (cur.left != null) queue.offer(cur.left);
if (cur.right != null) queue.offer(cur.right);
}
return root;
}
}
class Solution { // DFS前序
public TreeNode invertTree(TreeNode root) {
if (root == null) return root;
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
invertTree(root.right);
return root;
}
}
class Solution { // DFS后序
public TreeNode invertTree(TreeNode root) {
if (root == null) return root;
invertTree(root.left);
invertTree(root.right);
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
return root;
}
}
class Solution { // DFS中序第二个孩子要翻原来的右孩子,也就是新左孩子
public TreeNode invertTree(TreeNode root) {
if (root == null) return root;
invertTree(root.left);
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
return root;
}
}
https://leetcode.cn/problems/symmetric-tree/
做过的题又卡住了,卡住的原因在不知道如何两边同步一个从左遍历一个从右遍历,其实需要一个输入两个node的helper函数来实现。也可以两次遍历存下来再对比,但就需要n的space了。
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) return true;
return isSymmetric(root.left, root.right);
}
private boolean isSymmetric(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
if (left == null || right == null || left.val != right.val) return false;
return isSymmetric(left.right, right.left) && isSymmetric(left.left, right.right);
}
}