二叉树

二叉树结构面试题目及解法


用到的树形结构类

package Tree;
public class TreeNode {
    int value;
    TreeNode left;
    TreeNode right;
    public TreeNode(int value){
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

二叉树的遍历(先中后)

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();

        /**
         * 递归实现二叉树遍历
         * */
        treePractice.ergodic(root);
        /**
         * 非递归实现二叉树遍历
         * */
        //先序遍历
        System.out.print("先序");
        treePractice.preOrderErgodic(root);
        System.out.println();
        //后序遍历
        System.out.print("后序");
        treePractice.posOrderErgodic(root);
        System.out.println();
        //中序遍历
        System.out.print("中序");
        treePractice.inOrderErgodic(root);
        System.out.println();
    }
}

实现类:

​ 俩种实现方式:递归实现和非递归实现

package Tree;
import java.util.*;
public class TreePractice {
    /**
     * 递归实现数遍历
     * */
    public void ergodic(TreeNode root){
        if(root == null) return;
//        System.out.print(root.value+" ");  //先序遍历
        ergodic(root.left);
//        System.out.print(root.value+" ");  //中序遍历
        ergodic(root.right);
        System.out.print(root.value+" ");  //后序遍历
    }

    /**
     * 非递归实现数遍历
     * */
    /**
     * 先序遍历
     * 1、将根节点压进栈(后中序遍历和后序遍历相同,省略此步)
     * 2、弹出一个栈,打印
     * 3、判断是否有右节点,压进栈
     * 4、判断是否有左结点,压进栈
     * 5、循环
     * */
    public void preOrderErgodic(TreeNode root){
        if (root==null) return;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node = stack.pop();
            System.out.print(node.value+" ");
            if(node.right != null) stack.push(node.right);
            if (node.left != null) stack.push(node.left);
        }
    }

    /**
     * 后序遍历
     * 1、从第一个栈中弹出一个结点,存进收集栈
     * 2、循环第一步,直至所有结点都进第二个收集栈
     * 3、弹出并打印收集栈
     * */
    public void posOrderErgodic(TreeNode root){
        if (root==null) return;
        Stack<TreeNode> stack = new Stack<>();
        Stack<TreeNode> collectStack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node = stack.pop();
            collectStack.push(node);
            if(node.left!=null) stack.push(node.left);
            if(node.right!=null) stack.push(node.right);
        }
        while (!collectStack.isEmpty()){
            TreeNode node = collectStack.pop();
            System.out.print(node.value+" ");
        }
    }

    /**
     * 中序遍历
     * 1、将循环将结点的左节点全部压进栈
     * 2、当所有左节点压进去后,当前结点为null,弹出一个结点
     * 3、打印弹出的结点,判断该结点是否有右节点。如果有,当前结点变为该右节点
     * 4、循环
     * */
    public void inOrderErgodic(TreeNode root){
        if (root==null) return;
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || root != null){
            if(root != null){
                stack.push(root);
                root = root.left;
            }else {
                root = stack.pop();
                System.out.print(root.value + " ");
                root = root.right;
            }
        }
    }
}

题目一:求结点数最多的层

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();
		
        /**
         * 宽度优先遍历
         * 题目一: 求最多结点数的层数
         * */
        //使用队列和哈希表
        treePractice.getMaxByQueueAndMap(root);
        //使用队列
        treePractice.getMaxByQueue(root);
    }
}

实现类:

package Tree;
import java.util.*;
public class TreePractice {
    /**
     * 获取结点最多的层数
     *宽度优先遍历
     * */
    //使用队列和map
    public void getMaxByQueueAndMap(TreeNode root){
        if(root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        ((LinkedList<TreeNode>) queue).add(root);
        HashMap<TreeNode, Integer> levelMap = new HashMap<TreeNode, Integer>();
        int level = 1;
        levelMap.put(root,level);
        int number = 1;
        int max = Integer.MIN_VALUE;
        int maxLevel = Integer.MIN_VALUE;
        while(!queue.isEmpty()){
            TreeNode tmp = ((LinkedList<TreeNode>) queue).poll();
            int nodeLevel = levelMap.get(tmp);
            if(nodeLevel == level){ //还在同一层
                number++;
            }else {
                max = max>number?max:number;
                maxLevel = max > number?maxLevel:level;
                level++;
                number = 1;
            }
            if (tmp.left != null){
                ((LinkedList<TreeNode>) queue).add(tmp.left);
                levelMap.put(tmp.left,level+1);
            }
            if(tmp.right != null){
                ((LinkedList<TreeNode>) queue).add(tmp.right);
                levelMap.put(tmp.right,level+1);
            }
        }
        max = max>number?max:number;
        maxLevel = max > number?maxLevel:level;
        System.out.println(maxLevel+" 层的结点数为:"+max+" ,为最多");
    }

    //使用队列 俩个变量分别记录本层的最后一个结点和下一层的最后一个结点
    public void getMaxByQueue(TreeNode root){
        if (root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        ((LinkedList<TreeNode>) queue).add(root);
        TreeNode curEnd = root;
        TreeNode nextEnd = null;
        int level = 1;
        int max = Integer.MIN_VALUE;
        int number = 1;
        int maxLevel = Integer.MIN_VALUE;
        while (!queue.isEmpty()){
            TreeNode cur = queue.poll();
            if(cur.left != null){
                ((LinkedList<TreeNode>) queue).add(cur.left);
                nextEnd = cur.left;
            }
            if(cur.right != null){
                ((LinkedList<TreeNode>) queue).add(cur.right);
                nextEnd = cur.right;
            }
            if(cur != curEnd){
                number++;
            }else {
                max = max>number?max:number;
                maxLevel = max>number?maxLevel:level;
                level++;
                number = 1;
                curEnd = nextEnd;
            }
        }
        System.out.println(maxLevel+" 层的结点数为:"+max+" ,为最多");
    }
}

题目二:判断是否为搜索二叉树

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();
		
        /**
         * 搜索二叉树: 所有子树均满足: 左<中<右
         * 题目二: 判断二叉树是否是一棵二叉树
         * */
        boolean result = treePractice.isBST(root);
        System.out.println("是否为搜索二叉树:"+result);
    }
}

实现类:

package Tree;
import java.util.*;
public class TreePractice {
    /**
     * 判断是否是一棵搜索二叉树
     *使用中序遍历(中序遍历一定为升序)
     * */
    public int tmp = Integer.MIN_VALUE;
    public boolean isBST(TreeNode root){
        if(root == null) return true;
        boolean isBstLeft = isBST(root.left);
        if(!isBstLeft) return false;
        if(root.value <= tmp) return false;
        else tmp = root.value;
        boolean isBstRight = isBST(root.right);
        return isBstRight;
    }
}

题目三: 判断是否为完全二叉树

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();
		
        /**
         * 题目三: 判断是否是完全二叉树
         * */
        boolean result = treePractice.isCBT(root);
        System.out.println("是否为完全二叉树:"+result);
    }
}

实现类:

package Tree;
import java.util.*;
public class TreePractice {
   /**
     * 判断是否是完全二叉树
     * 使用宽度优先遍历
     * */
    public boolean isCBT(TreeNode root){
        if(root == null) return true;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        boolean isLeft = false;
        while (!queue.isEmpty()){
            TreeNode node = queue.poll();
            if((isLeft && (node.left != null || node.right != null)) || (node.left == null && node.right != null)){
                return  false;
            }
            if(node.left != null) queue.add(node.left);
            if(node.right != null) queue.add(node.right);
            if(node.left == null || node.left == null) isLeft = true;
        }
        return true;
    }
}

题目四:判断是否为平衡二叉树(树形DP套路解法)

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();
		
        /**
         * 题目四:判断是否是平衡二叉树
         * */
        ReturnType result = treePractice.isBalanced(root);
        System.out.println("该二叉树的层数有:"+result.height+" 是否为平衡二叉树:"+result.isBalanced);
    }
}

实现类:

package Tree;
import java.util.*;
public class TreePractice {
   /**
     * 判断是否为平衡二叉树
     * 树形DP *************
     * DP套路: 将整棵树递归分为左右子树,分别向左右子树获取需要的信息,在进行封装返回
     * */
    public ReturnType isBalanced(TreeNode root){
        if (root == null) return new ReturnType(true,0);
        ReturnType result = isBalancedproccess(root);
        return result;
    }
    public ReturnType  isBalancedproccess(TreeNode node){
        if(node == null) return new ReturnType(true,0);
        ReturnType left = isBalancedproccess(node.left);
        ReturnType right = isBalancedproccess(node.right);
        int height = Math.max(left.height,right.height)+1;
        boolean isBalanced = left.isBalanced && right.isBalanced && Math.abs(left.height - right.height) <2;
        return new ReturnType(isBalanced,height);
    }
}

题目五:判断是否是满二叉树(同树形DP套路解法)

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();
		
        /**
         * 题目五:判断是否是满二叉树
         * */
        boolean result = treePractice.isFullTree(root);
        System.out.println("是否为满二叉树:"+result);
    }
}

实现类:

package Tree;
import java.util.*;
public class TreePractice {
  /**
     * 判断是否是满二叉树
     * */
    public boolean isFullTree(TreeNode root){
        if(root == null) return true;
        ReturnType2 result = isFullTreeProccess(root);
        int number = (int) (Math.pow(2,result.height)-1);
        boolean isFull = result.number == (Math.pow(2,result.height)-1) ? true: false;
        return isFull;
    }
    public ReturnType2 isFullTreeProccess(TreeNode root){
        if(root == null) return new ReturnType2(0,0);
        ReturnType2 left = isFullTreeProccess(root.left);
        ReturnType2 right = isFullTreeProccess(root.right);
        int height = Math.max(left.height,right.height)+1;
        int number = left.number+right.number+1;
        return new ReturnType2(height,number);
    }
}

题目六:求俩个点的最低公共祖先

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();
		
        /**
         * 获取俩个结点的最小公共祖先
         * */
        //解法1:
        TreeNode result = treePractice.getPublicNode(root,rootRightLeft,rootRight);
        System.out.println("最小公共祖先是:"+result.value);
//        解法2
        TreeNode result = treePractice.getPublicNode2(root,rootRightLeft,rootRight);
        System.out.println("最小公共祖先是:"+result.value);
    }
}

实现类:

package Tree;
import java.util.*;
public class TreePractice {
  /**
     * 求俩个点的最低公共祖先
     * */
    //解法一:
    public TreeNode getPublicNode(TreeNode root,TreeNode node1,TreeNode node2){
        if(root == null) return null;
        HashMap<TreeNode,TreeNode> fatherMap = new HashMap<TreeNode, TreeNode>();
        fatherMap.put(root,root);
        setFatherProccess(root,fatherMap);
        HashSet<TreeNode> setNodeFather = new HashSet<TreeNode>();
        TreeNode cur1 = node1;
        while(cur1 != fatherMap.get(cur1)){
            setNodeFather.add(cur1);
            cur1 = fatherMap.get(cur1);
        }
        TreeNode cur2 = node2;
        while (cur2 != fatherMap.get(cur2)){
            if(setNodeFather.contains(cur2)) break;
            else{
                cur2 = fatherMap.get(cur2);
            }
        }
        return cur2;
    }
    //将所有结点的父节点放进哈希表
    public void setFatherProccess(TreeNode root,HashMap<TreeNode,TreeNode> fatherMap){
        if(root == null)return;
        fatherMap.put(root.left,root);
        fatherMap.put(root.right,root);
        setFatherProccess(root.left,fatherMap);
        setFatherProccess(root.right,fatherMap);
    }

    //解法二
    public TreeNode getPublicNode2(TreeNode root,TreeNode node1,TreeNode node2){
        if(root == null || root == node1 || root == node2) return root;
        TreeNode left = getPublicNode2(root.left,node1,node2);
        TreeNode right = getPublicNode2(root.right,node1,node2);
        if(left != null && right != null) return root;
        return  left != null? left:right;
    }
}

题目七: 二叉树的序列化和反序列化

主函数类:

package Tree;
public class TreeMatin {

    public static  void main(String[] agrs){
        //生成树形结构数据
        TreeNode root  = new TreeNode(1);
        TreeNode rootLeft = new TreeNode(2);
        TreeNode rootRight = new TreeNode(3);
        root.left= rootLeft;
        root.right = rootRight;
        TreeNode rootLeftLeft = new TreeNode(4);
        TreeNode rootLeftRight = new TreeNode(5);
        rootLeft.left = rootLeftLeft;
        rootLeft.right = rootLeftRight;
        TreeNode rootRightLeft = new TreeNode(6);
        TreeNode rootRightRight = new TreeNode(7);
        rootRight.left = rootRightLeft;
        rootRight.right = rootRightRight;
        TreePractice treePractice = new TreePractice();
		
        /**
         * 序列化
         * */
        String str = treePractice.serialByPre(root);
        System.out.println("序列化结果为:"+ str);

        /**
         * 反序列化
         * */
        TreeNode node = treePractice.reconByPreString(str);
        System.out.print("反序列化结果为:");
        treePractice.inOrderErgodic(node);
    }
}

实现类:

package Tree;
import java.util.*;
public class TreePractice {
 /**
     * 序列化
     * */
    public String serialByPre(TreeNode root){
        if(root == null) return "#_";
        String str = root.value+"_";
        str += serialByPre(root.left);
        str += serialByPre(root.right);
        return str;
    }

    /**
     * 反序列化
     * */
    public TreeNode reconByPreString(String str){
        String[] strList = str.split("_");
        Queue<String> queue = new LinkedList<String>();
        for (String string:strList) ((LinkedList<String>) queue).add(string);
        return reconByPreStringProccess(queue);
    }
    public TreeNode reconByPreStringProccess(Queue<String> queue){
        String str = queue.poll();
        if(str.equals("#")) return null;
        TreeNode node = new TreeNode(Integer.parseInt(str));
        node.left = reconByPreStringProccess(queue);
        node.right = reconByPreStringProccess(queue);
        return node;
    }
}

posted @ 2022-02-24 18:29  彬哙  阅读(30)  评论(0)    收藏  举报