层序遍历
102.二叉树的层序遍历
【思路】:看代码注释
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
// 记录返回的数据结果
public List<List<Integer>> resList = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrder(TreeNode root) {
// 迭代遍历
// iterateOrder(root);
recursionOrder(root, 0);
return resList;
}
public void iterateOrder(TreeNode node) {
if (node == null)
return;
// 节点队列
Queue<TreeNode> queue = new LinkedList<>();
// 将第一个节点加入队列,为第一层
queue.offer(node);
// 当队列不为空,保持队列一直有元素,如果没有说明树节点已经访问完了
while (!queue.isEmpty()) {
// 记录每层的元素
List<Integer> itemList = new ArrayList<>();
// 记录每一层的长度
int len = queue.size();
// 遍历每一层的每一个节点,将值加入到itemList中
while (len-- > 0) {
TreeNode tempNode = queue.poll();
itemList.add(tempNode.val);
// 加入每个节点的左右节点构成新层
if (tempNode.left != null)
queue.offer(tempNode.left);
if (tempNode.right != null)
queue.offer(tempNode.right);
}
// 将每层的元素加入到resList
resList.add(itemList);
}
}
// 递归方式
public void recursionOrder(TreeNode node, Integer deep) {
if (node == null)
return;
if (resList.size() == deep) {
// 当层级增加时,list的Item也增加,利用list的索引值进行层级界定
// 建立一个新空数组加到resList数组中
List<Integer> itemList = new ArrayList<>();
resList.add(itemList);
}
// 取出空数组,添加节点值
resList.get(deep).add(node.val);
recursionOrder(node.left, deep + 1);
recursionOrder(node.right, deep + 1);
}
}
107.二叉树的层次遍历 II
思路:将102的resList翻转即可,或者再加入层级数组itemList的时候每次加入到resList头部
199.二叉树的右视图
思路:判断最后一个节点,加入到List中
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> list = new ArrayList<>();
Deque<TreeNode> que = new LinkedList<>();
if (root == null) {
return list;
}
que.offerLast(root);
while (!que.isEmpty()) {
int levelSize = que.size();
for (int i = 0; i < levelSize; i++) {
TreeNode poll = que.pollFirst();
if (poll.left != null) {
que.addLast(poll.left);
}
if (poll.right != null) {
que.addLast(poll.right);
}
if (i == levelSize - 1) {
list.add(poll.val);
}
}
}
return list;
}
}
637.二叉树的层平均值
思路:记录每层的总和,再求平均值
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
// 节点队列
Queue<TreeNode> queue = new LinkedList<>();
// 记录元素
List<Double> resList = new ArrayList<>();
// 将第一个节点加入队列,为第一层
if (root == null)
return resList;
queue.offer(root);
// 当队列不为空,保持队列一直有元素,如果没有说明树节点已经访问完了
while (!queue.isEmpty()) {
// 记录每一层的长度
int len = queue.size();
//记录每一层的总和
Double sumVal = 0.0;
// 遍历每一层的每一个节点,将值加入到itemList中
for (int i = 0; i < len; i++) {
TreeNode tempNode = queue.poll();
sumVal += tempNode.val;
// 加入每个节点的左右节点构成新层
if (tempNode.left != null)
queue.offer(tempNode.left);
if (tempNode.right != null)
queue.offer(tempNode.right);
}
// 将每层的元素加入到resList
resList.add(sumVal / len);
}
return resList;
}
}
429.N叉树的层序遍历
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> list = new ArrayList<>();
Deque<Node> que = new LinkedList<>();
if (root == null) {
return list;
}
que.offerLast(root);
while (!que.isEmpty()) {
int levelSize = que.size();
List<Integer> levelList = new ArrayList<>();
for (int i = 0; i < levelSize; i++) {
Node poll = que.pollFirst();
levelList.add(poll.val);
List<Node> children = poll.children;
if (children == null || children.size() == 0) {
continue;
}
for (Node child : children) {
if (child != null) {
que.offerLast(child);
}
}
}
list.add(levelList);
}
return list;
}
}
515.在每个树行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
if(root == null){
return Collections.emptyList();
}
List<Integer> result = new ArrayList();
Queue<TreeNode> queue = new LinkedList();
queue.offer(root);
while(!queue.isEmpty()){
int max = Integer.MIN_VALUE;
for(int i = queue.size(); i > 0; i--){
TreeNode node = queue.poll();
max = Math.max(max, node.val);
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
result.add(max);
}
return result;
}
}
116.填充每个节点的下一个右侧节点指针
class Solution {
public Node connect(Node root) {
Queue<Node> tmpQueue = new LinkedList<Node>();
if (root != null)
tmpQueue.add(root);
while (tmpQueue.size() != 0) {
int size = tmpQueue.size();
Node preNode = null;
for (int index = 0; index < size; index++) {
Node curNode = tmpQueue.poll();
//第一个元素preNode要么不赋值,要么和curNode相等
// if (index == 0) {
// preNode = curNode;
// } else {
// preNode.next = curNode;
// preNode = curNode;
// }
//if( index !=0) {
// preNode.next = curNode;
}
// preNode = curNode;
//上下三种写法都可以
if (preNode != null)
preNode.next = curNode;
preNode = curNode;
if (curNode.left != null)
tmpQueue.add(curNode.left);
if (curNode.right != null)
tmpQueue.add(curNode.right);
}
preNode.next = null;
}
return root;
}
}
117.填充每个节点的下一个右侧节点指针II
思路:和117一模一样
104.二叉树的最大深度
思路:每次遍历的时候记录一下
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int depth = 0;
while (!que.isEmpty())
{
int len = que.size();
while (len > 0)
{
TreeNode node = que.poll();
if (node.left != null) que.offer(node.left);
if (node.right != null) que.offer(node.right);
len--;
}
depth++;
}
return depth;
}
}
111.二叉树的最小深度
思路:遍历每层节点时,判断每个节点的左右节点都是空的,如果是则直接返回当前层数
class Solution {
public int minDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int depth = 0;
while (!que.isEmpty())
{
int len = que.size();
//让depth先记录当前层数
depth++;
while (len-- > 0)
{
TreeNode node = que.poll();
if (node.left == null && node.right == null ) return depth;
if (node.left != null) que.offer(node.left);
if (node.right != null) que.offer(node.right);
}
}
return depth;
}
}
题目链接/文章讲解/视频讲解:programmercarl.com/0102.%E4%BA…
226.翻转二叉树 (优先掌握递归)
这道题目 一些做过的同学 理解的也不够深入,建议大家先看我的视频讲解,无论做过没做过,都会有很大收获。
//DFS递归
class Solution {
/**
* 前后序遍历都可以
* 中序不行,因为先左孩子交换孩子,再根交换孩子(做完后,右孩子已经变成了原来的左孩子),再右孩子交换孩子(此时其实是对原来的左孩子做交换)
*/
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
invertTree(root.left);
invertTree(root.right);
swapChildren(root);
return root;
}
private void swapChildren(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
// //BFS
// class Solution {
// public TreeNode invertTree(TreeNode root) {
// if (root == null) {return null;}
// ArrayDeque<TreeNode> deque = new ArrayDeque<>();
// deque.offer(root);
// while (!deque.isEmpty()) {
// int size = deque.size();
// while (size-- > 0) {
// TreeNode node = deque.poll();
// swap(node);
// if (node.left != null) deque.offer(node.left);
// if (node.right != null) deque.offer(node.right);
// }
// }
// return root;
// }
// public void swap(TreeNode root) {
// TreeNode temp = root.left;
// root.left = root.right;
// root.right = temp;
// }
// }
题目链接/文章讲解/视频讲解:programmercarl.com/0226.%E7%BF…
101. 对称二叉树 (优先掌握递归)
先看视频讲解,会更容易一些。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left, root.right);
}
private boolean compare(TreeNode left, TreeNode right) {
if (left == null && right != null) {
return false;
}
if (left != null && right == null) {
return false;
}
if (left == null && right == null) {
return true;
}
if (left.val != right.val) {
return false;
}
// 比较外侧
boolean compareOutside = compare(left.left, right.right);
// 比较内侧
boolean compareInside = compare(left.right, right.left);
return compareOutside && compareInside;
}
}
题目链接/文章讲解/视频讲解:programmercarl.com/0101.%E5%AF…
总结
题目好多呀,没想到一次性刷了那么多题,对递归还不是很熟悉,很多种遍历方式有点混乱,回头得再整理一下