二叉树的典型习题总结

2023-05-16

二叉树的三种遍历方式: 

1.给定一个二叉树,返回它的前序遍历。root-left-right

递归实现:

    public List<Integer> preorderTraversal(TreeNode root) {
       List<Integer> list = new ArrayList<>();  //每次遍历都会产生一个新的list对象
       if(root == null) {
           return list;
       } 
       System.out.print(root.val + " ");
       list.add(root.val);
       List<Integer> list1 = preorderTraversal(root.left);
       list.addAll(list1);
       List<Integer> list2 =  preorderTraversal(root.right);
       list.addAll(list2);
       return list;
      
    }

非递归实现: 

思路分析:【栈实现】  往左走,每走一次,cur不为空打印并入栈;为空拿到栈顶元素,cur= cur.right。

    void preOrderTraversalNor(TreeNode root) {
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.value + " ");
                cur = cur.left;
            }
            cur = stack.pop();
            cur = cur.right;
        }
    }
    List<Character> preOrderTraversalNor2(TreeNode root) {
       List<Character> list = new ArrayList<>();
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.value + " ");
                list.add(cur.value);
                cur = cur.left;
            }
            cur = stack.pop();
            cur = cur.right;
        }
        return list;
    }

2.给定一个二叉树,返回它的中序遍历。left-root-right

递归实现:

    public List<Integer> inorderTraversal(TreeNode root) {
       List<Integer> list = new ArrayList<>();
       if(root == null) {
           return list;
       } 
       List<Integer> list1 = inorderTraversal(root.left);
       list.addAll(list1);

       System.out.print(root.val + " ");
       list.add(root.val);

       List<Integer> list2 =  inorderTraversal(root.right);
       list.addAll(list2);
       return list;
    }

非递归实现:只是和前序遍历add的位置不同。 

  List<Character> preOrderTraversalNor2(TreeNode root) {
       List<Character> list = new ArrayList<>();
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
               stack.push(cur);
               cur = cur.left;
            }
            cur = stack.pop();
            list.add(cur.value);
            cur = cur.right;
        }
        return list;
    }

3.给定一个二叉树,返回它的后序遍历。 left-right-root

递归实现:

    public List<Integer> postorderTraversal(TreeNode root) {
       List<Integer> list = new ArrayList<>();
       if(root == null) {
           return list;
       } 
       List<Integer> list1 = postorderTraversal(root.left);
       list.addAll(list1);

       List<Integer> list2 =  postorderTraversal(root.right);
       list.addAll(list2);

       System.out.print(root.val + " ");
       list.add(root.val);

       return list;
    }

非递归实现:【栈实现】

    void postOrderTraversalnNor(TreeNode root) {
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        TreeNode prev = null;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            //cur = null;  ??
            cur = stack.peek();
            if(cur.right == null || cur.right == prev) {
                stack.pop();
                System.out.print(cur.value+" ");
                prev = cur;
                cur = null;
            }else {
                cur = cur.right;
            }
        }

    }
   public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        TreeNode prev = null;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            //cur = null;  异议
            cur = stack.peek();
            if(cur.right == null || cur.right == prev) {
                stack.pop();
                System.out.print(cur.val+" ");
                list.add(cur.val);
                prev = cur;
                cur = null;
            }else {
                cur = cur.right;
            }
        }
        return list;
    }

 

4.求节点个数

  //左子树的节点个数+右子树的节点的个数+1
  public int getSize(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return getSize(root.left) + getSize(root.right) +1;
    }

5.求叶子节点个数

      public int getLeafSize(TreeNode root) {
        if (root == null) {
            return 0;
        } else if (root.left == null && root.right == null) {
            return 1;
        }
        return getLeafSize(root.left) + getLeafSize(root.right);
    }

6.求第k层节点个数

思路分析:求当前root的第k层,就相当于当前root.left的k-1层+当前root.right的k-1层的节点个数

   int getKLevelSize(TreeNode root, int k) {
        if (root == null) {
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        return getKLevelSize(root.left, k-1) + getKLevelSize(root.right, k-1);
    }

7.查找val所在节点,没有找到返回null 根-左-右

    TreeNode find(TreeNode root, int val) {
        if (root == null) {
            return null;
        }
        if (root.value == val) {
            return root;
        }
        TreeNode ret = find(root.left, val);
        if (ret != null) {
            return ret;
        }
        ret = find(root.right, val);
        if (ret != null) {
            return ret;
        }
        return null;
    }

8.检查两棵树是否相同

   public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q != null || p != null && q == null) {
            return false;
        }
        if (p == null && q == null) {
            return true;
        }
        if (p.value != q.value) {
            return false;
        }
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }

9.另一颗树的子树

    public boolean isSubtree(TreeNode s, TreeNode t) {
        if (s == null || t == null) return false;
        if(isSameTree(s,t))  return true;
        if (isSameTree(s.left,t)) return true;
        if (isSameTree(s.right,t)) return true;
        return false;
    }

10.二叉树的最大深度

思路分析:最大深度就是节点的最大层次,也就是树的高度。那也就是左树的高度和右树的高度较大的值+1(root)

      public int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftHight = maxDepth(root.left);
        int rightHight = maxDepth(root.right);

        return leftHight > rightHight
                ? leftHight + 1 : rightHight + 1;
    }

11.判断一棵树是否为平衡二叉树
一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

思路分析:首先我们应该判断root节点是不是平衡的,如果是再判断root.left和root.right是不是平衡的。

 

    public boolean isBalanced(TreeNode root) {
        if(root == null) {
            return true;
        }
        int leftHight = maxDepth(root.left);
        int rightHight = maxDepth(root.right);

        return Math.abs(leftHight-rightHight) <= 1
        && isBalanced(root.left)
        && isBalanced(root.right);
    }


     public int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftHight = maxDepth(root.left);
        int rightHight = maxDepth(root.right);

        return leftHight > rightHight
                ? leftHight + 1 : rightHight + 1;
    }

12.镜像二叉树

思路分析:

首先有这样一幅图,我们会发现镜像二叉树有两个必要的条件①结构对称②对应位置数字必须相等。显然一个函数并不能解决问题。因此,以当前root为根节点,判断当前root是否为空。然后当root左树的值等于右树的值 &&  leftTree.left ,rightTree.right 是 镜像二叉树 && leftTree.right , rightTree.left镜像二叉树 三个条件同时成立该树才是镜像二叉树。

注意有两个特殊情况:图二 图三 图四。

       public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree) {
        if(leftTree == null && rightTree!= null ||  leftTree != null && rightTree == null) {
            return false;
        }
        if(leftTree == null && rightTree == null) {
            return true;
        }
        return leftTree.val == rightTree.val &&
        isSymmetricChild(leftTree.left,rightTree.right)
        &&isSymmetricChild(leftTree.right,rightTree.left);
    }
    public boolean isSymmetric(TreeNode root) {
        if(root == null) {
            return true;
        }
        return isSymmetricChild(root.left,root.right);
    }

13.层序遍历二叉树

    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<>();

        Queue<TreeNode> queue = new LinkedList<>();
        if(root != null) {
            queue.offer(root);
        }
        while (!queue.isEmpty()) {
            int size = queue.size();//1
            List<Integer> list = new ArrayList<>();
            while (size > 0) {
                TreeNode cur = queue.poll();
                System.out.print(cur.val+" ");
                list.add(cur.val);
                size--;//0
                if(cur.left != null) {
                    queue.offer(cur.left);
                }
                if(cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            ret.add(list);
        }
        return ret;
    }

14.判断一棵树是不是完全二叉树

思路分析:需要构造一个队列。当cur不为空时让cur入队列。当队列不为空时,让cur的左右节点入队列;当队列元素全为null时,说明这个树是完全二叉树;否则不是。

注意:如果是完全二叉树,遇到null 说明所有元素都放入队列 ;如果不是完全二叉树,那就不一定啦。

    boolean isCompleteTree(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<>();
        if(root != null) {
            queue.offer(root);
        }
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if(cur != null) {
                queue.offer(cur.left);
                queue.offer(cur.right);
            }else {
                break;
            }
        }

        while (!queue.isEmpty()) {
            TreeNode cur = queue.peek();
            if(cur != null) {
                return false;
            }else {
                queue.poll();
            }
        }
        return true;
    }

15.二叉树的构建及遍历

    public static int i = 0;
    public static TreeNode buildTree(String str) {
        TreeNode root = null;
        if(str.charAt(i) != '#') {
            root = new TreeNode(str.charAt(i));
            i++;
            root.left = buildTree(str);
            root.right = buildTree(str);
        }else {
            i++;
        }
        return root;
    }
//前序遍历的方式进行思考
class Solution {

    int preIndex = 0;

     public TreeNode buildTreeChild(int[] preorder,
    int[] inorder,int inbegin,int inend) {
         //判断是否有左树或者是右树
         if(inbegin > inend) {
             return null;
         }
         TreeNode root = new TreeNode(preorder[preIndex]);
         //找root在中序遍历的下标
         int rootIndex =
         findIndexOfInorder(inorder,inbegin,inend,preorder[preIndex]);
        preIndex++;

        root.left = buildTreeChild(preorder ,inorder,inbegin,
        rootIndex-1);

        root.right = buildTreeChild(preorder ,inorder
        ,rootIndex+1,inend);

        return root;
     }

     public int findIndexOfInorder(int[] inorder,int inbegin,
     int inend,int val){
         for(int i = inbegin;i <= inend;i++) {
             if(inorder[i] == val) {
                 return i;
             }
         }
         return -1;
     }


    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder == null || inorder == null) {
            return null;
        }
        if(preorder.length == 0 || inorder.length ==0) {
            return null;
        }

       return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }
}

 

16.给定一个二叉树,找到该树中两个指定节点的最近公共祖先

    public TreeNode find (TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) {
            return null;
        }
        if (root == p || root == q) {
            return root;
        }
        TreeNode leftTree = find(root.left, p, q);
        TreeNode rightTree = find(root.right, p, q);
        if (leftTree != null && rightTree != null) {
            return root;
        }
        if (leftTree != null) {
            return leftTree;
        }
        if (rightTree != null) {
            return rightTree;
        }
        return null;
    }

17.二叉搜索树转化为排序双向链表

    TreeNode prev = null; //标记上一个节点
    public void ConvertChild(TreeNode pCur) {
        if(pCur == null) {
            return;
        }
        ConvertChild(pCur.left);
        pCur.left = prev;
        if(prev != null) {
            prev.right = pCur;
        }
        prev = pCur;
        ConvertChild(pCur.right);
    }

    //返回的是双向链表的头结点
    public TreeNode Convert(TreeNode pRootOfTree) {
        //这个函数,执行完成后,二叉搜索树的结构已经被改变了
        ConvertChild(pRootOfTree);
        TreeNode head = pRootOfTree;
        //一路向左
        while (head != null && head.left != null) {
            head = head.left;
        }
        return head;
    }

 

18.根据一棵树的前序遍历和中序遍历构建二叉树

class Solution {

    int preIndex = 0;

     public TreeNode buildTreeChild(int[] preorder,
    int[] inorder,int inbegin,int inend) {
         //判断是否有左树或者是右树
         if(inbegin > inend) {
             return null;
         }
         TreeNode root = new TreeNode(preorder[preIndex]);
         //找root在中序遍历的下标
         int rootIndex =
         findIndexOfInorder(inorder,inbegin,inend,preorder[preIndex]);
        preIndex++;

        root.left = buildTreeChild(preorder ,inorder,inbegin,
        rootIndex-1);

        root.right = buildTreeChild(preorder ,inorder
        ,rootIndex+1,inend);

        return root;
     }

     public int findIndexOfInorder(int[] inorder,int inbegin,
     int inend,int val){
         for(int i = inbegin;i <= inend;i++) {
             if(inorder[i] == val) {
                 return i;
             }
         }
         return -1;
     }


    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder == null || inorder == null) {
            return null;
        }
        if(preorder.length == 0 || inorder.length ==0) {
            return null;
        }

       return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }
}

19..根据一棵树的中序遍历和后序遍历构建二叉树

class Solution {
    public int postIndex = 0;

    public TreeNode buildTreeChild(int[] inorder,
     int[] postorder,int inbegin,int inend) {
         //判断是否有左树或者是右树
         if(inbegin > inend) {
             return null;
         }
         TreeNode root = new TreeNode(postorder[postIndex]);
         //找root在中序遍历的下标
         int rootIndex =
         findIndexOfInorder(inorder,inbegin,inend,postorder[postIndex]);
        postIndex--;

          root.right = buildTreeChild(inorder
        ,postorder ,rootIndex+1,inend);


        root.left = buildTreeChild(inorder ,postorder,inbegin,
        rootIndex-1);


        return root;
     }

     public int findIndexOfInorder(int[] inorder,int inbegin,
     int inend,int val){
         for(int i = inbegin;i <= inend;i++) {
             if(inorder[i] == val) {
                 return i;
             }
         }
         return -1;
     }

    public TreeNode buildTree(int[] inorder, int[] postorder) {
     if(postorder == null || inorder == null) {
            return null;
        }
        if(postorder.length == 0 || inorder.length ==0) {
            return null;
        }
       postIndex = postorder.length-1;
       return buildTreeChild(inorder,postorder,0,inorder.length-1);
    }
}

20.二叉树创建字符串

 

class Solution {

    public void tree2strChild(TreeNode t,StringBuilder sb) {
        if(t == null) {
            return ;
        }
        sb.append(t.val);
        if(t.left == null) {
            if(t.right == null) {
                return;
            }else{
                sb.append("()");
            }
        }else{
            sb.append("(");
            tree2strChild(t.left,sb);
            sb.append(")");
        }
        //以上代码是递归前t的位置
        if(t.right == null) {
            return;
        }else{
            sb.append("(");
            tree2strChild(t.right,sb);
            sb.append(")");
        }

    }

    public String tree2str(TreeNode t) {
        StringBuilder sb = new StringBuilder();

        tree2strChild(t,sb);

        return sb.toString();
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉树的典型习题总结 的相关文章

随机推荐

  • 【LeetCode】剑指 Offer 67. 把字符串转换成整数 p318 -- Java Version

    题目链接 xff1a https leetcode cn problems ba zi fu chuan zhuan huan cheng zheng shu lcof 1 题目介绍 xff08 67 把字符串转换成整数 xff09 写一个
  • 【LeetCode】剑指 Offer 68. 二叉树中两个节点的最低公共祖先 p326 -- Java Version

    1 题目介绍 xff08 68 二叉树中两个节点的最低公共祖先 xff09 面试题68 xff1a 二叉树中两个节点的最低公共祖先 xff0c 一共分为两小题 xff1a 题目一 xff1a 二叉搜索树的最近公共祖先题目二 xff1a 二叉
  • 【华为机考】模拟题:Words、Vowel、计算字符串重新排列数

    前言 刷题之路任重而道远 xff0c 革命尚未成功 xff0c 同志仍需努力 由于刷惯了 LeetCode xff0c 虽然知道华为机考是需要自己输入输出 xff0c 也稍稍练了一下 xff0c 结果真做模拟题的时候 xff0c 一下子忘了
  • 【华为机考】专题突破 第二周:前缀和与差分 1109

    刷题顺序参考于 2023华为机考刷题指南 xff1a 八周机考速通车 前言 前缀和是指某序列的前n项和 xff0c 可以把它理解为数学上的数列的前n项和 xff0c 而差分可以看成前缀和的逆运算 合理的使用前缀和与差分 xff0c 可以将某
  • ROS学习和树莓派小车遇到问题汇总

    垃圾问题汇总记录 这里写目录标题 垃圾问题汇总记录我的小车配置中间遇到的问题汇总问题 xff1a VM虚拟机突然卡死问题 xff1a Error opening serial could not open port dev rikibase
  • ROS官网使用方式以及问题?

    Rviz中官网的使用 这里写目录标题 Rviz中官网的使用前言 xff08 希望瞄到这篇文章的大佬能注意一下 xff09 各种自带变量的官网查询方式一些普通消息类型的查询 xff1a Rviz等工具中的变量查询 xff1a 前言 xff08
  • automake自动编译工具

    automake自动编译生成makefile文件 xff0c 使用automake xff0c 程序开发人员只需要写简单的宏文件 xff0c 生成configure xff0c 再生成Makefile in xff0c 最终生成一个惯例的m
  • ROS中TF广播和监听个人理解及消息查找

    ROS学习古月居TF使用总结 目录 ROS学习古月居TF使用总结大佬链接总代码目录The Code of TFboardcastThe Code of TFlistenerThe Code of launch 广播和监听者的使用总结广播的创
  • Latex自动化学报模板学习和问题解决总结

    根据自动化学报模板的自己摸索 目录 根据自动化学报模板的自己摸索1 前言2 模板内部文件简介3 生成自己的模板4 内部代码理解关于aas cls和aas cfg文件整个模板固定结构 5 编译时有用的模板双栏显示用的小表格插入小图片 6 遇到
  • SLAM算法总结1

    目录 前言旋转矩阵 xff0c 旋转向量 xff0c 四元数李群李代数BCH公式非线性最小二乘一阶和二阶梯度法一阶梯度法二阶梯度法 xff08 牛顿法 xff09 高斯牛顿法代码实现手写 xff08 片段 xff09 用Ceres实现 xf
  • ROS下使用串口发送数据

    ROS下使用串口发送数据 span class token macro property span class token directive keyword include span span class token string lt
  • 新手如何使用postman(新手使用,简单明了)

    如何使用postman 一 了解postman 1 什么是postman xff1f 软件测试用来做接口测试的工具 2 如何下载postman https www getpostman com xff08 官方下载 xff09 链接 xff
  • 字符串的截取、分割,截取指定字符前面(后面)所有字符

    关于字符串截取问题 xff0c 从网上搜到总结一下 xff1a 已知一个字符串 xff0c 截取第一个指定字符后面所有字符 首先得知道indexof 34 34 的用法 xff0c 例如String i 61 abcdefg xff0c 那
  • [资料分享] 好赢60A无刷电调设置说明书【详细】

    完全针对车模而设计的全新程序算法 xff0c 具有优异的启动效果 加速性能 刹车性能及线性度 xff1b 支持所有无感 xff08 即无霍尔传感器 xff09 无刷电机 xff1b 高品质用料 xff0c 具有强大的耐电流能力 xff1b
  • 单片机学习笔记 —— 串口通信原理

    一 串口通信电路 电路图 xff1a 说明 xff1a 当RXD TXD为低电平时 xff0c 对应的led灯会亮起 二 串口通信控制寄存器 下图为80C51串行口的结构 xff1a SCON serial Control Register
  • 四种方法计算字符串的长度

    在这里我提供四种方法计算字符串的长度 1 使用递归函数 2 数数 xff0c 从第一个字符开始数数 xff0c 没遇到一个字符 xff0c 长度加一 xff0c 直到遇到 34 0 34 停止数数 3 使用strlen函数 xff0c 使用
  • 汉诺塔问题—C语言实现

    一 题目描述 相传在古印度圣庙中 xff0c 有一种被称为汉诺塔 Hanoi 的游戏 该游戏是在一块铜板装置上 xff0c 有三根杆 编号A B C xff0c 在A杆自下而上 由大到小按顺序放置64个金盘 如下图 游戏的目标 把A杆上的金
  • linux三大剑客

    awk是一种很棒的语言 xff0c 适合文本处理和报表生成 使用方法 awk pattern 43 action filenames 尽管操作可能会很复杂 xff0c 但是语法总是这样 xff0c 其中pattern表示AWK再数据中查找的
  • 数据结构与算法之栈

    目录 顺序栈 xff1a 链式栈 xff1a 栈的使用 xff1a 首先 xff1a 栈是一个特殊的线性表 xff0c 只允许在一端进行插入 xff08 压栈 xff09 和删除元素 xff08 进栈 xff09 xff0c 这一端称为栈顶
  • 二叉树的典型习题总结

    二叉树的三种遍历方式 xff1a 1 给定一个二叉树 xff0c 返回它的前序遍历 root left right 递归实现 xff1a public List lt Integer gt preorderTraversal TreeNod