LeetCode二叉树习题汇总
1. Num102——二叉树的层序遍历
1.1 问题描述
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
1.2 解析
package bin_tree.leetcode;
import java.util.*;
public class Num102_LevelOrder {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ret=new ArrayList<>();
if (root==null){
return ret;
}
// 借助队列实现二叉树的层序遍历过程
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
// 使用temp数组保存当前层的元素
List<Integer> curlist=new ArrayList<>();
//将当前层的元素取出存入curlist
int size=queue.size();
for (int i = 0; i < size; i++) {
TreeNode cur=queue.poll();
curlist.add(cur.val);
if (cur.left!=null){
queue.offer(root.left);
}
if (cur.right!=null){
queue.offer(root.right);
}
}
ret.add(curlist);
}
return ret;
}
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;
}
}
}
2 剑指 Offer 55 - II. 平衡二叉树
2.1 题目描述
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
2.2 解析
思路:计算二叉树左右子树高度,再判断左右子树高度相差是否超过1
package bin_tree.leetcode;
/**
* 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。
* 如果某二叉树中任意节点的左右子树的深度相差不超过1,
* 那么它就是一棵平衡二叉树
*/
// 思路:利用递归求左子树的深度leftmax和右子树的深度rightmax
// 当leftmax-rightmax的绝对值>1 不平衡
public class Offer55_isBalanced {
public boolean isBalanced(TreeNode root) {
if (root==null){
return true;
}
// 根节点左子树高度
int leftmax=getheight(root.left);
// 根节点右子树高度
int righttmax=getheight(root.right);
if (Math.abs(leftmax-righttmax)>1){
return false;
}else {
return true;
}
}
// 计算二叉树深度
public static int getheight(TreeNode root){
if (root==null){
return 0;
}
int leftheight=getheight(root.left);
int rightheight=getheight(root.right);
return Math.max(leftheight,rightheight)+1;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}
但上面的思路只是求了根节点的左右子树高度差,对下面这种情况就会出错,注意平衡二叉树需要每个节点都满足高度差不超过1的条件
正确代码
package bin_tree.leetcode;
/**
* 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。
* 如果某二叉树中任意节点的左右子树的深度相差不超过1,
* 那么它就是一棵平衡二叉树
*/
public class Offer55_isBalanced {
public boolean isBalanced(TreeNode root) {
if (root==null){
return true;
}
int leftmax=getheight(root.left);
int righttmax=getheight(root.right);
// 判断root的左子树和右子树的高度差以外,还要求每个结点的高度差是否满足条件
if ((Math.abs(leftmax-righttmax)<=1) && isBalanced(root.left) && isBalanced(root.right)){
return true;
}else {
return false;
}
}
// 计算二叉树深度
public static int getheight(TreeNode root){
if (root==null){
return 0;
}
int leftheight=getheight(root.left);
int rightheight=getheight(root.right);
return Math.max(leftheight,rightheight)+1;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}
3.剑指 Offer 28. 对称的二叉树
3.1 题目描述
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
3.2 解析
思路:二叉树的前序遍历 根左右
对称前序遍历 根右左
若二叉树为对称二叉树则二叉树的前序遍历结果和对称前序遍历 结果相同
细节:一定要注意保存空结点(若不存储空结点,则结构有可能不同)
package bin_tree.leetcode;
import bin_tree.MyBinTree;
import java.util.ArrayList;
import java.util.List;
/**
* 思路:二叉树的前序遍历 根左右
* 对称前序遍历 根右左
* 若二叉树为对称二叉树则二叉树的前序遍历结果和对称前序遍历 结果相同
* 细节:一定要注意保存空结点
*/
public class Num101_isSymmetric {
// 创建两个列表保存二叉树的前序、对称前序遍历结果
List<Integer> ret=new ArrayList<Integer>();
List<Integer> ret1=new ArrayList<Integer>();
public boolean isSymmetric(TreeNode root) {
// 若根节点为空,直接返回false
if(root==null){
return false;
}
// ret保存二叉树前序遍历节点值
ret=preorderTraversal(root);
// ret1保存二叉树前序兑成遍历节点值
ret1=preorderTraversal1(root);
// 判断两种遍历结果是否相同
return ret.equals(ret1);
}
public List<Integer> preorderTraversal(TreeNode root){
if (root==null){
ret.add(null);
return ret;
}
ret.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return ret;
}
public List<Integer> preorderTraversal1(TreeNode root){
if (root==null){
ret1.add(null);
return ret1;
}
ret1.add(root.val);
preorderTraversal1(root.right);
preorderTraversal1(root.left);
return ret1;
}
/**
* 创建一个二叉树,返回根节点
*/
public static TreeNode build() {
// 创建8个节点
TreeNode nodeA = new TreeNode('1');
TreeNode nodeB = new TreeNode('2');
TreeNode nodeC = new TreeNode('2');
TreeNode nodeD = new TreeNode('3');
TreeNode nodeE = new TreeNode('4');
TreeNode nodeF = new TreeNode('4');
TreeNode nodeG = new TreeNode('3');
// 将这8个节点进行连接
nodeA.left = nodeB;
nodeA.right = nodeC;
nodeB.left = nodeD;
nodeB.right = nodeE;
nodeC.left = nodeF;
nodeC.right = nodeG;
return nodeA;
}
public static 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;
}
}
public static void main(String[] args) {
TreeNode root=build();
Num101_isSymmetric a=new Num101_isSymmetric();
System.out.println(a.isSymmetric(root));
}
}
4.Num100—— 相同的树
4.1 题目描述
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
3.2 解析
若两个二叉树相同,则用同样的遍历方式遍历的结果是相同的
/**
* 思路:二叉树的前序遍历 根左右
* 若二叉树为相同的二叉树则二叉树的前序遍历结果结果相同
* 细节:一定要注意保存空结点
*/
public class Num100_isSameTree{
// 创建两个列表保存二叉树的前序遍历结果
List<Integer> ret=new ArrayList<Integer>();
List<Integer> ret1=new ArrayList<Integer>();
public boolean isSameTree(TreeNode p, TreeNode q) {
// 若根节点为空,直接返回false
if(p==null && q!=null){
return false;
} if(p!=null && q==null){
return false;
}
// ret保存P二叉树前序遍历节点值
ret=preorderTraversal(p,ret);
// ret1保存q二叉树前序遍历节点值
ret1=preorderTraversal(q,ret1);
// 判断两种遍历结果是否相同
return ret.equals(ret1);
}
public List<Integer> preorderTraversal(TreeNode p,List<Integer> ret){
if (p==null){
ret.add(null);
return ret;
}
ret.add(p.val);
preorderTraversal(p.left,ret);
preorderTraversal(p.right,ret);
return ret;
}
/**
* 创建一个二叉树,返回根节点
*/
public static TreeNode build() {
TreeNode nodeA = new TreeNode(1);
TreeNode nodeB = new TreeNode(2);
TreeNode nodeC = new TreeNode(1);
nodeA.left = nodeB;
nodeA.right = nodeC;
return nodeA;
}
public static TreeNode build1() {
TreeNode nodeA = new TreeNode(1);
TreeNode nodeB = new TreeNode(1);
TreeNode nodeC = new TreeNode(2);
nodeA.left = nodeB;
nodeA.right = nodeC;
return nodeA;
}
public static 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;
}
}
public static void main(String[] args) {
TreeNode p=build();
TreeNode q=build1();
Num100_isSameTree a=new Num100_isSameTree();
System.out.println(a.isSameTree(p,q));
}
}
5 剑指 Offer 26. 树的子结构
5.1 题目描述
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
5.2 解析
package bin_tree.leetcode;
import bin_tree.MyBinTree;
/**
* 输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
* B是A的子结构, 即 A中有出现和B相同的结构和节点值。
*/
public class offer26_isSubStructure {
public boolean isSubStructure(TreeNode A, TreeNode B) {
// 若两个根节点其中一个为空 则返回false
if (A==null || B==null){
return false;
}
return isrootsub(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
}
public static boolean isrootsub(TreeNode root,TreeNode sub){
// 判断sub是否为null,若sub为空 则匹配成功
if (sub==null){
return true;
}
// 若sub子结构没有匹配完,但root已经走完
if(root==null){
return false;
}
// 若两个结点的值不同,则返回false
if (root.val!=sub.val){
return false;
}
// 递归判断其余结点
return isrootsub(root.left,sub.left)&& isrootsub(root.right,sub.right);
}
public static TreeNode build(){
TreeNode nodeA=new TreeNode(4);
TreeNode nodeB=new TreeNode(2);
TreeNode nodeC=new TreeNode(3);
TreeNode nodeD=new TreeNode(4);
TreeNode nodeE=new TreeNode(5);
TreeNode nodeF=new TreeNode(6);
TreeNode nodeG=new TreeNode(7);
TreeNode nodeH=new TreeNode(8);
TreeNode nodeI=new TreeNode(9);
nodeA.left=nodeB;
nodeA.right=nodeC;
nodeB.left=nodeD;
nodeB.right=nodeE;
nodeD.left=nodeH;
nodeD.right=nodeI;
nodeC.left=nodeF;
nodeC.right=nodeG;
return nodeA;
}
public static TreeNode build1(){
TreeNode nodeA=new TreeNode(4);
TreeNode nodeB=new TreeNode(8);
TreeNode nodeC=new TreeNode(9);
nodeA.left=nodeB;
nodeA.right=nodeC;
return nodeA;
}
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public static void main(String[] args) {
TreeNode A=build();
TreeNode B=build1();
offer26_isSubStructure a=new offer26_isSubStructure();
System.out.println(a.isSubStructure(A,B));
}
}