102. 二叉树的层序遍历
给你二叉树的根节点
root
,返回其节点值的 层序遍历。 (即逐层地,从左到右访问所有节点)。
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
对于二叉树的层序遍历,需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
解题思路:
- 定义一个二维列表用来存储最终结果
- 定义队列
- 将root添加到队列当中
- 如果队列不为空,设置一个一维列表用来存储二叉树每一层的遍历结果,计算二叉树的层数,每一层分别去遍历,从左往右
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> reslut=new ArrayList<>();
Deque<TreeNode> que=new LinkedList<>();
if(root==null){
return reslut;
}
que.offer(root);
while(!que.isEmpty()){
List<Integer> res=new ArrayList<>();
int size=que.size();
while(size>0){
TreeNode node=que.poll();
res.add(node.val);
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
size--;
}
reslut.add(res);
}
return reslut;
}
}
107. 二叉树的层序遍历 II
给你二叉树的根节点
root
,返回其节点值 自底向上的层序遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]
107和102类似,思路可以使将结果保存到链表当中,依旧按照层序遍历,但是每一层的结果都加到链表的最前面
LinkedList<List<Integer>> result=new LinkedList<>();
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
LinkedList<List<Integer>> result=new LinkedList<>();
Deque<TreeNode> deq=new LinkedList<>();
if(root==null){
return result;
}
deq.offer(root);
while(!deq.isEmpty()){
List<Integer> res=new ArrayList<>();
int size=deq.size();
for(int i=0;i<size;i++){
TreeNode node=deq.poll();
res.add(node.val);
if(node.left!=null){
deq.offer(node.left);
}
if(node.right!=null){
deq.offer(node.right);
}
}
result.addFirst(res);
}
return result;
}
}
199. 二叉树的右视图
给定一个二叉树的 根节点
root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
输入: [1,2,3,null,5,null,4]
输出: [1,3,4]
这道题主要要判断每一层的最后一个元素,将其添加到结果列表当中
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> reslut=new ArrayList<>();
Deque<TreeNode> deq=new LinkedList<>();
if(root==null){
return reslut;
}
deq.offer(root);
while(!deq.isEmpty()){
int size=deq.size();
while(size>0){
TreeNode node=deq.poll();
if(node.left!=null){
deq.offer(node.left);
}
if(node.right!=null){
deq.offer(node.right);
}
if(size==1){
reslut.add(node.val);
}
size--;
}
}
return reslut;
}
}
637. 二叉树的层平均值
给定一个非空二叉树的根节点
root
, 以数组的形式返回每一层节点的平均值。与实际答案相差10-5
以内的答案可以被接受。
输入:root = [3,9,20,null,null,15,7]
输出:[3.00000,14.50000,11.00000]
将每一层的元素均相加,但是这里要注意除的size需要提前备份,不然每次while循环在减少
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> reslut=new ArrayList<>();
Deque<TreeNode> deq=new LinkedList<>();
if(root==null){
return reslut;
}
deq.offer(root);
while(!deq.isEmpty()){
int size=deq.size();
int len=size;
double temp=0.0;
while(len-->0){
TreeNode node=deq.poll();
temp+=node.val;
if(node.left!=null){
deq.offer(node.left);
}
if(node.right!=null){
deq.offer(node.right);
}
}
reslut.add(temp/size);
}
return reslut;
}
}
429. N 叉树的层序遍历
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]
这道题的不同点在于,每个结点有N个子结点,所以需要遍历结点里面的所有子结点
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> reslut=new ArrayList<>();
Deque<Node> que=new LinkedList<>();
if(root==null){
return reslut;
}
que.offer(root);
while(!que.isEmpty()){
List<Integer> res=new ArrayList<>();
int size=que.size();
while(size-->0){
Node cur=que.poll();
res.add(cur.val);
for(Node next:cur.children){
que.offer(next);
}
}
reslut.add(res);
}
return reslut;
}
}
515.在每个树行中找最大值
给定一棵二叉树的根节点
root
,请找出该二叉树中每一层的最大值。
输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> reslut=new ArrayList<>();
Deque<TreeNode> que=new LinkedList<>();
if(root==null){
return reslut;
}
que.offer(root);
while(!que.isEmpty()){
int size=que.size();
int max=que.getFirst().val;
while(size-->0){
TreeNode node=que.poll();
max=Math.max(max,node.val);
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
}
reslut.add(max);
}
return reslut;
}
}
104.二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
class Solution {
public int maxDepth(TreeNode root) {
Deque<TreeNode> que=new LinkedList<>();
if(root==null){
return 0;
}
que.offer(root);
int depth=0;
while(!que.isEmpty()){
int size=que.size();
while(size-->0){
TreeNode node=que.poll();
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
}
depth++;
}
return depth;
}
}
111. 二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
输入:root = [3,9,20,null,null,15,7]
输出:2
和求最大深度相比,最小深度需要判断node的左右节点均为空。
class Solution {
public int minDepth(TreeNode root) {
Deque<TreeNode> que=new LinkedList<>();
if(root==null){
return 0;
}
que.offer(root);
int depth=0;
while(!que.isEmpty()){
int size=que.size();
depth++;
while(size-->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;
}
}
116. 填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为
NULL
。初始状态下,所有 next 指针都被设置为
NULL
。
输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
在遍历的过程中修改每个节点的 next\text{next}next 指针,同时拓展下一层的新队列。
class Solution {
public Node connect(Node root) {
if(root==null) return root;
Deque<Node> deq=new LinkedList<>();
deq.offer(root);
while(!deq.isEmpty()){
int size=deq.size();
for(int i=0;i<size;i++){
Node node=deq.poll();
if(i<size-1){
node.next=deq.peek();
}
if(node.left!=null){
deq.offer(node.left);
}
if(node.right!=null){
deq.offer(node.right);
}
}
}
return root;
}
}
117. 填充每个节点的下一个右侧节点指针 II
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为
NULL
。
输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
class Solution {
public Node connect(Node root) {
Queue<Node> que=new LinkedList<>();
if(root==null) return root;
que.offer(root);
while(!que.isEmpty()) {
int size = que.size();
for(int i=0;i<size;i++){
Node node=que.poll();
if(i==size-1){
node.next=null;
}else{
Node new1=que.peek();
node.next=new1;
}
if(node.left!=null) que.offer(node.left);
if(node.right!=null) que.offer(node.right);
}
}
return root;
}
}
226. 翻转二叉树
给你一棵二叉树的根节点
root
,翻转这棵二叉树,并返回其根节点。
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
思路一:BFS
class Solution {
public TreeNode invertTree(TreeNode root) {
Deque<TreeNode> deq=new LinkedList<>();
if(root==null) return root;
deq.offer(root);
while(!deq.isEmpty()){
int size=deq.size();
while(size-->0){
TreeNode node=deq.poll();
swap(node);
if(node.left!=null) deq.offer(node.left);
if(node.right!=null) deq.offer(node.right);
}
}
return root;
}
public void swap(TreeNode root){
TreeNode temp=root.left;
root.left=root.right;
root.right=temp;
}
}
思路二:递归
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null) return root;
invertTree(root.left);
invertTree(root.right);
swap(root);
return root;
}
public void swap(TreeNode root){
TreeNode temp=root.left;
root.left=root.right;
root.right=temp;
}
}
101. 对称二叉树
给你一个二叉树的根节点
root
, 检查它是否轴对称。
输入:root = [1,2,2,3,4,4,3]
输出:true
思路一:递归
将root的左右节点分别进行递归比较
class Solution {
public boolean isSymmetric(TreeNode root) {
return comparable(root.left,root.right);
}
public boolean comparable(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 ouside=comparable(left.left,right.right);
boolean inside=comparable(left.right,right.left);
return ouside&&inside;
}
}
思路二:BFS
class Solution {
public boolean isSymmetric(TreeNode root) {
return compara(root,root);
}
public boolean compara(TreeNode root1,TreeNode root2){
Deque<TreeNode> deq=new LinkedList<>();
deq.offer(root1);
deq.offer(root2);
while(!deq.isEmpty()){
root1=deq.poll();
root2=deq.poll();
if(root1==null&&root2==null){
continue;
}
if((root1==null||root2==null)||(root1.val!=root2.val)){
return false;
}
deq.offer(root1.left);
deq.offer(root2.right);
deq.offer(root1.right);
deq.offer(root2.left);
}
return true;
}
}