欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 【数据结构】二叉树(三)精选Oj题

【数据结构】二叉树(三)精选Oj题

2024/10/24 18:16:24 来源:https://blog.csdn.net/m0_73107796/article/details/141228501  浏览:    关键词:【数据结构】二叉树(三)精选Oj题

本篇已经是二叉树第三篇啦,下面讲解相关面试题,写作不易,求路过的朋友给个点赞与收藏呀~

目录

1、相同的树

2、另一颗树的子树 

 3、翻转二叉树

 4、对称二叉树

5、平衡二叉树

 6、构建二叉树

7、二叉树的最近公共祖先

孩子双亲解法

二叉搜索树解法 

普通二叉树解法    

8、二叉树创建字符串


判断两棵树是否相同、另一颗的子树、反转二叉树、判断是否为平衡二叉树、对称二叉树、二叉树的构建、最近公共祖先结点、根据前序与中序遍历构造二叉树、根据后序与中序遍历构造二叉树、二叉树创建字符串

1、相同的树

解题思路:

同时遍历两棵树

  1. 如果两棵树都是空,则相同
  2. 如果两棵树一个为空,一个不为空,则不相同
  3.  如果两棵树都不为空,先检测值是否相同,根如果相同再递归检测两棵树的左子树以及右子树是否都相同
class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {// 判断结构if (p == null && q == null) {return true;}// 判断结构       if (p == null || q == null) {return false;}// 判断值相等if (p.val != q.val)return false;return isSameTree(p.left, q.left) &&isSameTree(p.right, q.right);}
}

2、另一颗树的子树 

解题思路:

  1. 空树是任意一棵树的子树
  2. 如果两棵树相同,也可以认为是子树,因此:只要根节点相同,直接检测s和t是否为相同的树即可
  3. 如果根不相同,检测t是否为s.left的子树 或者 s.right的子树 

class Solution {//判断subRoot是否为root子树public boolean isSubtree(TreeNode root, TreeNode subRoot) {if (root == null) {return false;}
//subRoot可能与root相同,可能与root.left 、root.right相同
//其中一种情况为true,则为子树return isSameTree(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);}//判断参数中两树是否相同public boolean isSameTree(TreeNode p, TreeNode q) {if (p == null && q == null) {return true;} else if (p == null || q == null) {return false;} else if (p.val != q.val) {return false;} else {return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);}}
}

【易错点】

        return isSameTree(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);

(root.left, subRoot)与(root.right, subRoot)参数应传入Subtree方法中进行递归,若传入isSameTree方法中只能判断一次root的左右子树与subRoot是否相同


 3、翻转二叉树

解题思路:

二叉树前序遍历规则应用, 如果树不空时:

  1. 交换根的左右子树
  2. 递归反转根的左子树
  3. 递归反转根的右子树 
class Solution {public TreeNode invertTree(TreeNode root) {if(root==null)return null;//借助ret将root.left、root.right交换TreeNode ret=null;ret=root.left;root.left=root.right;root.right=ret;//递归反转根的左子树invertTree(root.left);
//递归反转根的右子树 invertTree(root.right);return root;}
}

 4、对称二叉树

 

解题思路:

直接递归检测root的左右是否对称即可

  1. 如果两棵树都是空树,则对称
  2. 如果两棵树一棵为空树,一棵不为空树,则一定不是对称树
  3. 如果两棵树都不为空,先检测两棵树的root是否相同,如果相同,再检测一个的left是否为另一个的right 并且一个的right是否为另一个的left
class Solution {public boolean isSymmetric(TreeNode root) {return isSym(root.left, root.right);}//判断对称public boolean isSym(TreeNode p, TreeNode q) {if(p==null&&q==null)return true;if(p!=null&&q==null||p==null&&q!=null)return false;if(p.val!=q.val)return false;return isSym(p.left,q.right)&&isSym(p.right,q.left); }
}

5、平衡二叉树

平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1。

解题思路:

平衡二叉树的概念:二叉树中每个节点左右子树高度差的绝对值不能超过1 根据概念来检测:

  1. 如果是空树,直接返回,注意:空树也是平衡二叉树
  2. 求根的左右子树高度,然后做差检测其高度差的绝对值是否超过1 如果超过则不是
  3. 递归检测根的左右子树是否为平衡二叉树
class Solution {
//计算root的深度public int GetHeight(TreeNode root){if(root == null){return 0;}int leftHeight = GetHeight(root.left);int rightHeight = GetHeight(root.right);
//三目运算符,root深度为左右子树更大值加1return leftHeight > rightHeight? leftHeight+1 : rightHeight+1;}//判断是否平衡public boolean isBalanced(TreeNode root) {// 空树是平衡二叉树if(root == null){return true;}// 获取root左右子树的高度int leftHeight = GetHeight(root.left);int rightHeight = GetHeight(root.right);// 根据平衡树的概念,检测root节点的平衡性if(Math.abs(rightHeight - leftHeight) >= 2){return false;}// 通过递归方式:检测root的左右子树是否为平衡树return isBalanced(root.left) && isBalanced(root.right);}
}

 6、构建二叉树

这道题偏难,可以点进牛客网链接测试,链接放这里啦

根据字符串构建二叉树

//结点类
class TreeNode {char val;TreeNode left;TreeNode right;public TreeNode(char val) {this.val = val;}
}
public class Main {static int i = 0;//创建二叉树public static TreeNode setUp(String str) {TreeNode node = null;//依次取出str字符串的每个字符char ch = str.charAt(i);if (ch != '#') {node = new TreeNode(ch);i++;node.left = setUp(str);node.right = setUp(str);} else {i++;}return node;}//中序遍历public static void inOrderTraversal(TreeNode root) {if (root == null)return;inOrderTraversal(root.left);System.out.print(root.val + " ");inOrderTraversal(root.right);}
//main方法public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNext()) { // 注意 while 处理多个 caseString str = in.nextLine();TreeNode root = setUp(str);inOrderTraversal(root);}}
}

 注意事项

OJ算法题分为两种类型:

  1. 接口类型OJ:此种OJ题目是方法名字已经给好,用户直接写代码即可,也不需要包含什么包
  2. IO类型的OJ:此种OJ题目需要用户定义一个public的Main类,然后在Main类中提供一个main方法,在main方法中完成事情,中间如要需要用到其他集合类,必须手动 导入包 在线OJ中的循环输入,输入单个值怎么循环接收,整行值怎么循环接收

7、二叉树的最近公共祖先

这道题有多种解法 对二叉树分情况:

孩子双亲解法

如果二叉树采用孩子双亲表示法链接,求两个节点的最近公共祖先,实际就转化为两个链表相交求交点  

二叉搜索树解法 

a. 如果树是空,直接返回null,没有最近公共祖先节点

b. 如果两个节点中有一个是根节点,最近公共祖先一定是根节点

c. 如果两个节点一个比根节点大,一个比根节点小,最近公共祖先一定是根节点

d. 如果两个节点都比根节点小,递归到根的左子树中查找

e. 如果两个节点都比根节点大,递归到根的右子树中查找        

普通二叉树解法    

 方法一:

写一个判断节点是否在二叉树中的方法,可以参考类似二叉搜索树的方法解觉

  • 如果树是空,直接返回null,没有最近公共祖先节点
  • 如果两个节点中有一个是根节点,最近公共祖先一定是根节点
  • 如果两个节点一个在根节点的左子树,一个在根节点的右子树,最近公共祖先一定是根节点
  • 如果两个节点都在左子树中,递归到左子树中找
  • 如果两个节点都在右子树中,递归到右子树中找    

方法二:受孩子双亲表示法启发,如果能够知道节点到根的路径,问题就解决了

获取节点pNode的路径,因为公共祖先从下往上找,因此将路径中的节点保存在栈中

  • 如果是空树,直接返回 
  • 将根节点入栈,如果根节点和pNode是同一个节点,该节点到根的路径找到,否则:
  • 递归在根节点的左子树中查找,如果找到,返回
  • 如果在根节点的左子树中未找到,递归到根节点的右子树中找
  • 如果右子树中没有找到,说明root一定不再路径中                 

方法三:将两个节点的路径存入栈中

  1.   在二叉树中获取两个节点的路径
  2. 如果两个路径中节点个数不一样,节点多的出栈,直到两个栈中元素相等
  • 相等时:再比较两个栈顶是不是同一个节点,
  • 如果是,最近公共祖先找到。
  • 如果不是,两个栈同时进行出栈,继续比较,直到找到为止   

下面以 普通二叉树解法 方法一举例,代码有注释哈

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if (root == null)return null;if (root == p)return p;if (root == q)return q;// 找出root的左子树是否有p/q结点TreeNode leftTree = lowestCommonAncestor(root.left, p, q);// 找出root的右子树是否有p/q结点TreeNode rightTree = lowestCommonAncestor(root.right, p, q);// 若左右子树都不为空,说明找到了p、q,则最近祖先为rootif (rightTree != null && leftTree != null)return root;// 若左子树不为空右子树为空,最近祖先为root.leftif (leftTree != null)return leftTree;// 若左子树为空右子树不为空,最近祖先为root.rightreturn rightTree;}
}

8、二叉树创建字符串

 解题思路: 采用二叉树前序遍历规则进行转化

  1. 如果树空,转化结束
  2. 如果树非空
  • 先转化跟节点
  • 转化根节点的左子树, 如果根的左子树非空或者左子树空但是右子树非空:( 递归转化左子树 ), 注意将转化结果内嵌到()中
  • 转化根节点的右子树 ,如果根的右子树非空:( 递归转化右子树 ), 注意将转化结果内嵌到()中
class Solution {
String str;public String tree2str(TreeNode t) {StringBuilder sb = new StringBuilder();tree2str(t, sb);return sb.toString();}public void tree2str(TreeNode t, StringBuilder str) {if(null == t){return;}// 先将根节点的数据放到str中str.append(t.val);// 处理根节点的左子树if(null != t.left || null != t.right){// 左子树非空,递归转化左子树str.append("(");tree2str(t.left, str);str.append(")");}// 再检测t的右子树,如果右子树为空,不增加任何内容if(null != t.right){// 递归处理右子树str.append("(");tree2str(t.right, str);str.append(")");}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com