❣博主主页: 33的博客❣
▶文章专栏分类: Java从入门到精通◀
🚚我的代码仓库: 33的代码仓库🚚
🫵🫵🫵关注我带你学更多数据结构的知识
目录
- 1.前言
- 2.经典习题
- 2.1相同的树
- 2.2另一棵子树
- 2.3翻转二叉树
- 2.4平衡二叉树
- 2.5对称二叉树
- 2.6二叉树的构建及遍历
- 2.7二叉树的分层遍历
- 3.总结
1.前言
在上一篇文章中,博主主要介绍了树与二叉树的基本概念、二叉树概念及特性、遍历方式自己实现一棵二叉树,在这篇文章中,博主将继续与大家分享二叉树经典习题。
2.经典习题
2.1相同的树
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同:OJ链接
解题思路
递归思想:
1.如果p为空,q为空,那么就是两颗空树肯定相等
2.如果一个树为空另一棵树不为空那么一定不相等
3.如果都不为空,值相同才相等。
4.在递归判断左子树是否相等,右子树是否相等,只有左右子树都相等才是相同的树
class Solution {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 boolean isSameTree(TreeNode p, TreeNode q) {if(p==null&&q==null){return true;}//p、q有一个为空if(p==null&&q!=null||p!=null&&q==null){return false;}//两个都不为空,不相等if(p.val!=q.val){return false;}//两个都不为空且p=qreturn isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);}
}
2.2另一棵子树
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树:OJ链接
解题思路
递归思想
1.如果其中一个为null那么就不是子树
2.如果是两棵相同的树,那么就为一定为子树
3.再递归看sub是否为左子树的子树,右子树的子树,如果都不是,则返回false
public boolean isSubtree(TreeNode root, TreeNode subRoot) {if(root == null &&subRoot!=null|| subRoot == null&&root!=null) {return false;}if(isSameTree(root,subRoot)){return true;} if(isSubtree(root.left,subRoot)){return true;} if(isSubtree(root.right,subRoot)){return true;}return false;}
2.3翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树:OJ链接
解题思路
1.判断是否为空树,判断这棵树是否只有根节点
2.再交换左右子树
public TreeNode invertTree(TreeNode root) {if(root==null||root.left==null&&root.right==null){return root;}TreeNode tmp= root.left;root.left=root.right;root.right=tmp;invertTree(root.left);invertTree(root.right);return root;}
2.4平衡二叉树
给定一个二叉树,判断它是否是 平衡二叉树(左右子树相差不超过1):OJ链接
解题思路
递归思想
1.先求一个树深度
2.求左子树的深度,再求右子树的深度,相差>1则不平衡
3.并且左子树和右子树的每一个个小树都要平衡
public boolean isBalanced(TreeNode root) {if(root==null){return true;}int left=MaxLength(root.left);int right=MaxLength(root.right);if (Math.abs(left-right)<=1&&isBalanced(root.right)&&isBalanced(root.left)){return true;}else {return false;}}public int MaxLength(TreeNode root){if (root==null){return 0;}int Left=MaxLength(root.left);int Right=MaxLength(root.right);return Left>Right?Left+1:Right+1;}
我们观察以上代码,我们发现在求长度的时候已经遍历了一次二叉树,但在求是否平衡的时候,每次递归又会再求高度再遍历数组,效率非常低。那有能不能在求高度的时候就可以判断子树是否平衡呢?答案是可以的,如下:
当求高度的时候先先判断左子树和右子树只差是否小于1,如果小于1就返回-1,就不会再往递归了。
public boolean isBalanced(TreeNode root) {if(root==null){return true;}return MaxLength(root)>0;}public int MaxLength(TreeNode root){if (root==null){return 0;}int Left=MaxLength(root.left);int Right=MaxLength(root.right);if(Left>=0&&Right>=0&&Math.abs(Left-Right)<=1){return Math.max(Left,Right)+1;}else return -1;}
2.5对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称:OJ链接
解题思路
1.判断root是否为null
2.比较左子树和右子树是否对称
3.若其中一棵树为null,那么不对称,若都为null则对称
4.再判断,左子树的左节点是否等于右子树的右节点&&左子树的右节点等于右子树的左节点,依次递归。
class Solution {public boolean isSymmetric(TreeNode root){if(root==null){return true;}else {return isSymmetric(root.left,root.right);}}public boolean isSymmetric(TreeNode L,TreeNode R){if(L==null&&R==null){return true;}if(L==null&&R!=null||L!=null&&R==null){return false;}if(L.val!= R.val){return false;}return isSymmetric(L.left,R.right)&&isSymmetric(L.right,R.left);}
}
2.6二叉树的构建及遍历
读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树:OJ链接
解题思路
1.遍历字符串,不为#,就new一个Node,但在遍历字符串的时候,我们要把i设置为成员变量防止每次递归后i从0开始
2.遍历二叉树中序输出
class TreeNode{char val;TreeNode left;TreeNode right;public TreeNode(char val) {this.val = val;}
}
public class Main {static int i=0;public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseString str=in.nextLine();TreeNode root= createTree(str);inOrder(root);}}public static TreeNode createTree(String str) {
// for (int i=0;i<str.length();i++) {
// char ch = str.charAt(i);i每次则从0开始TreeNode root=null;if(str.charAt(i)!='#'){root=new TreeNode(str.charAt(i));i++;root.left=createTree(str);root.right=createTree(str);}else {i++;//不要担心i超出字符串长度的问题}return root;}public static void inOrder(TreeNode root){if(root==null){return ;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}
}
2.7二叉树的分层遍历
分层遍历二叉树:OJ链接
解题思路
我们需要借助队列来实现,当root不为null时,那么我们将root入队,再将它出队打印,出对的时候我们添加左子树,添加右子树,循环上述操作,直到独队列为空。
public void order(TreeNode root){Queue<TreeNode> queue=new LinkedList<>();if(root==null){return;}queue.offer(root);while (!queue.isEmpty()){TreeNode cur=queue.poll();System.out.println(cur.val+" ");if(cur.left!=null){queue.add(cur.left);}if (cur.right!=null){queue.add(cur.right);}}}
除了递归的方式,还可以用非递归的方式:
public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> list=new ArrayList<>();if(root==null){return list;}Queue<TreeNode> queue=new LinkedList<>();queue.offer(root);while (!queue.isEmpty()){int size=queue.size();List<Integer> l=new ArrayList<>();while (size!=0){TreeNode cur=queue.poll();size--;l.add(cur.val);if(cur.left!=null){queue.add(cur.left);}if (cur.right!=null){queue.add(cur.right);}}list.add(l);}return list;}
3.总结
在这篇文章中,博主主要分享了比较容易的一些二叉树题目,我们发现在做二叉树的习题时,大多都有用到递归思想,因为二叉树的子树本身也是一棵二叉树,所以当同学们遇到关于二叉树的问题时,可以往递归方向思考。在下一篇文章中,将继续和大家分享二叉树中比较复杂的题目。
下期预告:二叉树经典习题(下)