二叉树层序遍历
层序遍历
题目:给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
思路:使用一个size记录每一层的数量,然后进行输出
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new LinkedList<>();
if(root == null){
return res;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
int size = deque.size();// 记录每一层有多少个元素
List<Integer> ans = new LinkedList<>();
while(size --> 0){
TreeNode node = deque.pollFirst();
ans.add(node.val);
if(node.left != null){// 将左孩子入队
deque.addLast(node.left);
}
if(node.right != null){// 将右孩子入队
deque.addLast(node.right);
}
}
res.add(ans);
}
return res;
}
}
层序遍历||
题目:给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
方法一
直接在上面代码return之前反转一下list即可:Collections.reverse(res);
方法二
在插入结果集合的时候始终往第一个位置插入即可
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new LinkedList<>();
if(root == null){
return res;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
int size = deque.size();// 记录每一层有多少个元素
List<Integer> ans = new LinkedList<>();
while(size --> 0){
TreeNode node = deque.pollFirst();
ans.add(node.val);
if(node.left != null){// 将左孩子入队
deque.addLast(node.left);
}
if(node.right != null){// 将右孩子入队
deque.addLast(node.right);
}
}
res.add(0,ans);// 这里始终插入在0位置,最后就实现了从底层开始输出的效果
}
return res;
}
}
二叉树的右视图
题目:给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
思路:还是层序遍历,就是在每一次的最右一个元素就是最右侧的元素
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new LinkedList<>();
if(root == null){
return res;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
int size = deque.size();// 还是需要记录一下每一层的大小,最后一个就是最右侧的元素
for(int i = 0;i<size;i++){
TreeNode node = deque.pollFirst();
if(i == size - 1){// 最后一个就是最右侧的元素
res.add(node.val);
}
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
}
return res;
}
}
二叉树的层平均值
题目:给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。
思路:层序遍历,然后每层统计一下平均值
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new LinkedList<>();
if(root == null){
return res;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
double sum = 0d;
int size = deque.size();
for(int i = 0;i<size;i++){
TreeNode node = deque.pollFirst();
sum+=node.val;
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
res.add(sum/size);
}
return res;
}
}
N叉树的层序遍历
题目:给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
思路:使用队列存放元素,二叉树是在出队的时候将其左右孩子入队,这里就是将其所有孩子节点入队
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new LinkedList<>();
if(root == null){
return res;
}
Deque<Node> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
List<Integer> ans = new LinkedList<>();
int size = deque.size();
while(size --> 0){
Node node = deque.pollFirst();
ans.add(node.val);
if(node.children != null){
for(Node n : node.children){
deque.addLast(n);
}
}
}
res.add(ans);
}
return res;
}
}
在每个树行中找到最大值
题目:给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
思路:依旧是层序遍历,在每一行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new LinkedList<>();
if(root == null){
return res;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
int size = deque.size();
int max = Integer.MIN_VALUE;
while(size --> 0){
TreeNode node = deque.pollFirst();
max = Math.max(max,node.val);
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
res.add(max);
}
return res;
}
}
填充每个节点的下一个右节点指针
题目:给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点
思路:层序遍历,将每一层的前n-1个元素连接起来,最后一个元素指向null
class Solution {
public Node connect(Node root) {
if(root == null){
return root;
}
Deque<Node> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
int size = deque.size();
for(int i = 0;i<size;i++){
Node node = deque.pollFirst();
if(i < size - 1){// 只连接每一层的,这个判断防止当前层的最后一个元素连接到下一层的第一个元素了
node.next = deque.peek();
}
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
}
return root;
}
}
填充每个节点的下一个右节点指针||
题目:填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。
初始状态下,所有 next 指针都被设置为 NULL 。
同上
class Solution {
public Node connect(Node root) {
if(root == null){
return null;
}
Deque<Node> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
int size = deque.size();
for(int i = 0;i<size;i++){
Node node = deque.pollFirst();
if(i < size - 1){
node.next = deque.peek();
}
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
}
return root;
}
}
二叉树的最大深度
题目:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点
思路:层序遍历,每一层统计高度
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
int depth = 0;
while(!deque.isEmpty()){
int size = deque.size();
while(size --> 0){
TreeNode node = deque.pollFirst();
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
depth++;
}
return depth;
}
}
二叉树的最小深度
题目:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
思路:层序遍历,遇到了左右孩子都为null的时候,说明遇到了叶子节点,可以返回深度了
class Solution {
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
int depth = 1;// 因为根节点不为空,所有从1开始
while(!deque.isEmpty()){
int size = deque.size();
while(size --> 0){
TreeNode node = deque.pollFirst();
if(node.left == null && node.right == null){// 遇到了叶子节点
return depth;
}
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
depth++;
}
return depth;
}
}
翻转二叉树
题目:给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
递归
思路:使用递归的方式,然后采用前序或者后序遍历进行交换节点
前序遍历
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null){
return null;
}
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
invertTree(root.right);
return root;
}
}
后序遍历
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null){
return null;
}
invertTree(root.left);
invertTree(root.right);
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
return root;
}
}
中序遍历
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null){
return null;
}
invertTree(root.left);
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);// 中序遍历的话,这里就不能是右子树了,因为当前的右子树是反转前的左子树(已经被交换过了),当前的左子树是反转前的右子树(还没有反转的节点)
return root;
}
}
迭代
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null){
return null;
}
Deque<TreeNode> deque = new ArrayDeque<>();
deque.addLast(root);
while(!deque.isEmpty()){
int size = deque.size();
while(size --> 0){
TreeNode node = deque.pollFirst();
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
if(node.left != null){
deque.addLast(node.left);
}
if(node.right != null){
deque.addLast(node.right);
}
}
}
return root;
}
}
对称二叉树
题目:给你一个二叉树的根节点 root , 检查它是否轴对称。
递归
思路:采用后序遍历,判断左右孩子是否相等
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null){
return true;
}
return compare(root.left,root.right);
}
private 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;
}else{// 左右两个节点的值相等,就往下继续遍历
// 左 右
boolean outSide = compare(left.left,right.right);// 判断外侧是否相等
// 右 左
boolean inSide = compare(left.right,right.left);//判断内侧是否相等
// 中
return outSide && inSide;
}
}
}
迭代
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null){
return true;
}
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root.left);
deque.addLast(root.right);
while(!deque.isEmpty()){
TreeNode l = deque.pollFirst();
TreeNode r = deque.pollFirst();
if(l == null && r == null){
continue;// 此处不能返回true,因为虽然当前节点相同,但是可能后面的左右子树存在不是对称的
}
if(l != null && r == null){
return false;
}
if(l == null && r != null){
return false;
}
if(l.val != r.val){
return false;
}
deque.addLast(l.left);
deque.addLast(r.right);
deque.addLast(l.right);
deque.addLast(r.left);
}
return true;
}
}