IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 面试中不可少的二叉树试题 -> 正文阅读

[数据结构与算法]面试中不可少的二叉树试题

前序遍历和和中序遍历还原二叉树

链接:前序+中序还原二叉树

在这里插入图片描述
在这里插入图片描述

思路

  • 在前序遍历结果中确定二叉树的根结点(原因:前序遍历是先遍历根结点,在遍历根的左子树,后遍历根的右子树);
  • 在中序遍历结果中找根的位置 pos,以 pos 为分界点,左边为根的左子树元素所处的位置,右边为根的右子树元素所处的位置;
  • 还原根结点;
  • 递归还原根的左子树;
  • 递归还原根的右子树

代码实现

class Solution {
    int index=0; //用来标记前序遍历中根的位置
    TreeNode rebuilderTree(int[] preorder,int[] inorder,int left, int right){
        if(index>=preorder.length || left >= right){
            return null;
        }
        //从中序遍历结果中确定根的左右两颗子树位置元素
        int pos=left;
        while(pos<right){
            if(inorder[pos]==preorder[index]){
                //表明找到了根结点
                break;
            }
            pos++;
        }
        // 从前序遍历结果中确定根,即index的位置 preorder[index]就是根的位置
        //还原二叉树的根结点
        TreeNode root=new TreeNode(preorder[index]);
         index++;

        //递归还原根的左子树
        root.left=rebuilderTree(preorder,inorder,left,pos);

        //递归还原根的右子树
        root.right=rebuilderTree(preorder,inorder,pos+1,right);

        return root;

    }
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        index=0;
        return rebuilderTree(preorder, inorder,0,inorder.length);
    }
}

中序遍历和和后序遍历还原二叉树

链接:中序+后序还原二叉树

在这里插入图片描述

思路

  • 在后序遍历结果中确定二叉树的根结点(原因:后序遍历是先遍历根的左子树,再遍历根的右子树,最后遍历根结点);
  • 在中序遍历结果中找根的位置 pos,以 pos 为分界点,左边为根的左子树元素所处的位置,右边为根的右子树元素所处的位置;
  • 还原根结点;
  • 递归还原根的右子树;
  • 递归还原根的左子树

代码实现

class Solution {
        int index=0; //用来标记前序遍历中根的位置
    TreeNode rebuilderTree(int[] postorder,int[] inorder,int left, int right){
        if(index<0 || left >= right){
            return null;
        }
        //从中序遍历结果中确定根的左右两颗子树位置元素
        int pos=left;
        while(pos<right){
            if(inorder[pos]==postorder[index]){
                //表明找到了根结点
                break;
            }
            pos++;
        }
        // 从前序遍历结果中确定根,即index的位置 postorder[index]就是根的位置
        //还原二叉树的根结点
        TreeNode root=new TreeNode(postorder[index]);
         index--;

        //递归还原根的右子树
        root.right=rebuilderTree(postorder,inorder, pos+1,right);

        //递归还原根的左子树
        root.left=rebuilderTree(postorder,inorder,left ,pos);

        return root;

    }
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        index=postorder.length-1;
        return rebuilderTree(postorder, inorder,0,inorder.length);

    }
}

二叉树构造字符串

链接:二叉树构造字符串

在这里插入图片描述

思路

该题目用到字符串,由于 string是不可变类型,要拼接所以使用 stringbuilder

注意题目中的左括号是不能省略的,要不然分不清左右子树的位置

代码实现

class Solution {
    public void preorder(TreeNode root, StringBuilder str) {
          //树为空
        if (root == null) {
            return;
        }
		//转换根结点(就是打印)
        str.append(root.val);
        //递归转换根的左子树
        //分下面两个情况
        if (root.left != null) {
            str.append('(');
            preorder(root.left, str);
            str.append(')');
        }
        if (root.left == null && root.right != null) {
            str.append('(');
            str.append(')');
        }
        //递归转换根的右子树
        if (root.right != null) {
            str.append('(');
            preorder(root.right, str);
            str.append(')');
        }
    }

    public String tree2str(TreeNode root) {

        StringBuilder str = new StringBuilder();
        preorder(root, str);
        return str.toString();
    }
}

求二叉树的最近公共祖先

链接:公共祖先
在这里插入图片描述
在这里插入图片描述

思路

可以分三种情况来分析讨论:
情况一:该二叉树采用双亲表示法或者是采用孩子双亲表示法;
求公共祖先就变成了两个链表相交求交点的问题了;

在这里插入图片描述

情况二
该二叉树如果为二叉搜索树,所谓二叉搜索树就是对于每个结点而言,都满足:(1)根结点大于根的左子树结点;(2)根结点小于根的右子树结点
求公共祖先就有以下四种方式
假设给定的两个结点,一个为 x,一个为 y
(1)当x == rooty ==root时,最近的公共祖先一定为根结点;(原因:根结点是所有结点的祖先)
(2)当 x .data< root.data && y.data>root.data 时 ,或者当 x .data> root.data && y.data<root.data,最近的公共祖先也是根结点(原因:x, y处在根结点的两侧);
(3)当x .data< root.data && y.data<root.data 时,此时,x和y都处于根的左子树中,因此求最近的公共祖先就直接到根的左子树中找;
(4)当x .data> root.data && y.data>root.data 时,此时,xy都处于根的右子树中,因此求最近的公共祖先就直接到根的右子树中找;

情况三:该二叉树就是一棵普通的二叉树;

那么

  • 受情况一的启发,只要找到从根结点出发的到某个结点的路径中遇到那些结点,并将其保存;因为当路径中的结点找到之后,需要从下往上进行比较,因此借助栈来保存;
    在这里插入图片描述
    该种情况下

(1)当栈中所存元素不相等时,让元素多的出栈
(2)相同且值域不同时,同时出栈
(3)公共祖先就是栈中元素个数相同时且值域也相同的元素

代码实现

class Solution {
    //获取根结点到某个结点对应路径中的所有遇到的结点
    boolean getPathNode(TreeNode root,Stack<TreeNode> sPath,TreeNode node ){
        if(node ==null || root==null){
            //树为空或者结点为空
            return false;
        }

        sPath.push(root);
        if(root==node){
        //表明是同一个结点
            return true;
        }
        //左子树中找
        if(getPathNode(root.left,sPath,node)){
            return true;
        }
          //右子树中找
         if(getPathNode(root.right,sPath,node)){
            return true;
        }
        sPath.pop();
        return false;
    }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //检测给定参数
        if(root==null ||p==null ||q==null){
            return null;
        }
      //找从root到p,q 对应路径中包含的所有结点
      //保存到栈中
      Stack<TreeNode> pPath=new Stack();
      Stack<TreeNode> qPath=new Stack();
      getPathNode(root,pPath,p);
      getPathNode(root,qPath,q);

      int pSize=pPath.size();
      int qSize=qPath.size();
      while(!pPath.empty() && !qPath.empty()){
          if(pPath.peek()==qPath.peek()){
              return pPath.peek();
          }
          if(pSize>qSize){
          //让多的出栈
              pPath.pop();
              pSize--;
          }else if(pSize<qSize){
              qPath.pop();
              qSize--;
          }else{
          //两个一样多时,同时出栈
              pPath.pop();
              qPath.pop();
              pSize--;
              qSize--;
          }
      }

        return null;
    }
}
  • 同样的,受情况二启发:
  • 如果知道一个结点在其子树中的位置,也能找到公共祖先;

代码如下

class Solution {
    boolean isNodeInTree(TreeNode root,TreeNode node){
        //检测结点是否在树中
        if(root==null || node ==null){
            return false;
        }

        if(root==node){
            return true;
        }

        if(isNodeInTree(root.left,node)){
            return true;
        }

          
        return isNodeInTree(root.right,node);

    }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //空树
        if(root==null){
            return null;
        }

        //树不为空
        //p 和q 有一个在根的位置,公共祖先就是根
        if(p == root|| q == root){
            return root;
        }

        boolean ispInLeft=false;
        boolean ispInRight=false;
        boolean isqInLeft=false;
        boolean isqInRight=false;

        //检测p是否在root的左子树中
        if(isNodeInTree(root.left,p)){
            ispInLeft=true;
            ispInRight=false;

        }else{
             ispInLeft=false;
             ispInRight=true;
        }

        
         //检测q是否在root的左子树中
        if(isNodeInTree(root.left,q)){
            isqInLeft=true;
            isqInRight=false;

        }else{
             isqInLeft=false;
             isqInRight=true;
        }
       //检测p和q是否都在root的左子树中
        if(ispInLeft && isqInLeft){
            return lowestCommonAncestor(root.left,p,q);
        }else if(ispInRight && isqInRight){
            return lowestCommonAncestor(root.right,p,q);

        }else{
            return root;
        }
    }
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-09 19:49:07  更:2021-11-09 19:53:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 1:49:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码