二叉树的面试题目总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a1b2c3d4123456/article/details/52556193
主要涉及:
二叉树的遍历、路径和、翻转、镜像、子树、和链表转换

1。二叉树的先序遍历

    List<Integer> res=new ArrayList<Integer>();
    public static List<Integer> preOrder(TreeNode root){
        if(root==null) return res;
        res.add(root.val);
        preOrder(root.left);
        preOrder(root.right);
        return res;
    }

2。二叉树的中序遍历

    List<Integer> res=new ArrayList<Integer>();
    public static List<Integer> inOrder(TreeNode root){
        if(root==null) return res;
        inOrder(root.left);
        res.add(root.val);
        inOrder(root.right);
        return res;
    }

3。二叉树的后序遍历

    List<Integer> res=new ArrayList<Integer>();
    public static List<Integer> afterOrder(TreeNode root){
        if(root==null) return res;
        afterOrder(root.left);
        afterOrder(root.right);
        res.add(root.val);
        return res;
    }

4、层次遍历,使用一个队列作为存储

    public static List<Integer> levelOrder(TreeNode root){
        List<List<Integer>> res=new ArrayList<>();
        if(root==null) return res;
        Queue<TreeNode> q=new LinkedList<TreeNode>();
        q.add(root);
        while(!q.isEmpty()){
            int n=q.size();
            List<Integer> tmp=new ArrayList<>();
            for(int i=0;i<n;i++){
                TreeNode node=q.poll();
                tmp.add(node.val);
                if(node.left!=null) q.add(node.left);
                if(node.right!=null) q.add(node.right);
            }
            res.add(tmp);//res.add(index,value);可以放到指定的位置
        }
        return res;
    }

5、zigzag就是层次遍历的时候偶数层是从左向右,奇数层从右向左。使用两个栈为实现,记录当前层和下一层

    public static List<List<Integer>> zigLevel(TreeNode root){
        List<List<Integer>> res=new ArrayList<>();
        if(root==null) return res;
        Stack<TreeNode> currlevel=new Stack<TreeNode>();
        Stack<TreeNode> nextlevel=new Stack<TreeNode>();
        currlevel.add(root);
        boolean flag=true;
        while(!currlevel.isEmpty()){
            List<Integer> currResult=new ArrayList<Integer>();
            while(!currlevel.isEmpty()){
                TreeNode node=currlevel.pop();
                currResult.add(node.val);
                if(flag){
                    if(node.right!=null){
                        nextlevel.push(node.right);
                    }
                    if(node.left!=null){
                        nextlevel.push(node.left);
                    }
                }
                else{
                    if(node.left!=null){
                        nextlevel.push(node.left);
                    }
                    if(node.right!=null){
                        nextlevel.push(node.right);
                    }
                }
            }
            res.add(currResult);
            Stack<TreeNode> tmp=currlevel;
            currlevel=nextlevel;
            nextlevel=tmp;
            flag=!flag;         
        }
        return res;
    }

6,二叉树的镜像翻转

    public static TreeNode mirrorReverse(TreeNode root){
        if(root==null) return root;
        TreeNode tmp=mirrorReverse(root.left);
        root.left=mirrorReverse(root.right);
        root.right=tmp;
        return root;
    }

7,判断二叉树是不是镜像二叉树,前序遍历和镜像前序遍历

    public static boolean mirrorTree(TreeNode root){
        if(root==null) return false;
        return helper(root,root);
    }
    public static boolean helper(TreeNode root1,TreeNode root2){
        if(root1==null&&root2==null) return true;
        if(root1==null||root2==null) return false;
        if(root1.val!=root2.val) return false;
        return helper(root1.left,root2.right)&&helper(root1.right,root2.left);
    }

8,判断两个二叉树是不是相同

    public static boolean sameTree(TreeNode root1,TreeNode root2){
        if(root1==null&&root2==null) return true;
        if(root1==null||root2==null) return false;
        if(root1.val!=root2.val) return false;
        return sameTree(root1.left,root2.left)&&sameTree(root1.right,root2.right);
    }

9,判断一个树是不是两一个树的子结构

    public static boolean isSubtree(TreeNode root1,TreeNode root2){
        if(root1==null&&root2==null) return true;
        if(root1==null) return false;
        boolean flag=false;
        if(root1!=null&&root2!=null){
            if(root1.val==root2.val){
                flag=match(root1,root2);
            }
            if(!flag){
                flag=isSubtree(root1.left,root2);
            }
            if(!flag){
                flag=isSubtree(root1.right,root2);
            }
        }
        return flag;
    }

    public static boolean match(TreeNode root1,TreeNode root2){
        if(root1==null) return false;
        if(root2==null) return true;
        if(root1.val!=root2.val) return false;
        return match(root1.left,root2.left)&&match(root1.right,root2.right);
    }


10,判断一个序列是不是二叉搜索树的后序遍历,搜索树是左<中<右,后续遍历是左右中,找到左子树和递归判断

    public static boolean isPopstOrder(int[] a,int start,int to){
        if(a.length<0) return false;
        int index=start;
        while(index<to-1&&a[index]<a[to]){
            index++;
        }
        int i=index;
        while(index<to-1&&a[index]>a[to]){
            index++;
        }
        if(index!=to-1){
            return false;
        }
        return isPopstOrder(a,start,index-1)&&isPopstOrder(a,index,to-1);       
    }

11,把一个二叉搜索树转换成双向链表

    public static TreeNode converse(TreeNode root){
        if(root==null) return null;
        if(root.left==null&&root.right==null){
            return root;
        }
        TreeNode left=converse(root.left);
        TreeNode p=left;
        while(p.right!=null&&p!=null){
            p=p.right;
        }
        if(left!=null){
            p.right=root;
            root.left=p;
        }
        TreeNode right=converse(root.right);
        if(right!=null){
            right.left=root;
            root.right=right;
        }
        return left!=null?left:root;
    }


12,重建二叉树,根据前序遍历和中序遍历递归构建左右子树,  

    public static class BinaryTreeNode {
            int value;
            BinaryTreeNode left;
            BinaryTreeNode right;
        }

    public static BinaryTreeNode rebuildTree(int [] prerder,int [] inOrder){
        if(prerder==null||inOrder==null||preOrder.length!=inOrder.length) return null;
        return (preOrder,0,preOrder.length-1,inOrder,0,inOrder.length-1);
    }

    public static BinaryTreeNode helper(int [] preOrder,int ps,int pe,int [] inOrder,int is,int ie){
        if(ps>pe) return null;
        int val=preOrder[ps];
        int index=is;
        while(index<=ie&&inOrder[index]!=val){
            index++;
        }
        BinaryTreeNode node=new BinaryTreeNode();
        node.val=val;
        node.left(preOrder,ps+1,ps+index-is,inOrder,is,index-1);
        node.right(preOrder,ps+index-is+1,pe,inOrder,index+1,ie);
        return node;
    }

13,二叉树的最大深度

    public static int maxDep(TreeNode root){
        if(root==null) return 0;
        return Math.max(maxDep(root.left),maxDep(root.right))+1;
    }

14,二叉树的最小深度

    public static int minDep(TreeNode root){

        if(root==null) return 0;
        if(root.left==null) return minDep(root.right)+1;
        if(root.right==null) return minDep(root.left)+1;
        return Math.min(minDep(root.left),minDep(root.right))+1;
    }

15,判断二叉树的路径和是否有一条和给定的目标值一样

    public static boolean pathSum(TreeNode root,int val){
        if(root==null) return false;
        if(root.left==null&&root.right==null&&root.val==val){
            return true;
        }
        return pathSum(root.left,val-root.val)||pathSum(root.right,val-root.val);
    }

16,找出所有路径和为目标值的路径来

    int[] save=new int[1000];
    List<List<Integer>> res=new ArrayList<>();
    public static List<List<Integer>> pathSum(TreeNode root,int val){

        if(root==null) return res;
        helper(root,val,0);
        return res;
    }

    public static void helper(TreeNode root,int val,int index){
        if(root==null) return;
        save[index]=root.val;
        if(root.val==val&&root.left==null&&root.right==null){
            List<Integer> tmp=new ArrayList<>();
            for(int i=0;i<=index;i++){
                tmp.add(save[i]);
            }
            res.add(tmp);
            return;
        }
        helper(root.left,val-root.val,index+1);
        helper(root.right,val-root.val,index+1);
    }

17,求出二叉树的所有的叶子节点

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

18,判断是不是平衡二叉树

    public static boolean balanceTree(TreeNode root){
        if(root==null) return false;
        if(Math.abs(maxDep()-maxDep())>1) return false;
        return balanceTree(root.left)&&balanceTree(root.right);
    }

    public static int maxDep(TreeNode root){
        if(root==null) return 0;
        return Math.max(maxDep(root.left),maxDep(root.right))+1;
    }

19,二叉树的所有路径和,1-2-3的路径和看做是123

    public static int sumTree(TreeNode root){
        if(root==null) return 0;
        return helper(root,0);
    }
    public static int helper(TreeNode root,int sum){
        if(root==null) return 0;
        if(root.left==null&&root.right==null){
            return sum*10+root.val;
        }
        return helper(root.left,sum*10+root.val)+helper(root.right,sum*10+root.val);
    }

20,树中叶子节点的最低公共祖先,使用链表存储到2个叶子节点的路径,然后去寻找链表的最后一个公共节点,如果是二叉树就简单点

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == p || root == q || root == null) { return root; }
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        return (left != null && right != null) ? root : (left != null ? left : right);
    }

    二叉搜索树会更简单一点

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        int max = Math.max(p.val, q.val);
        int min = Math.min(p.val, q.val);
        while (!(max >= root.val && min <= root.val))
            root = root.val < min ? root.right : root.left;
        return root;
    }























猜你喜欢

转载自blog.csdn.net/a1b2c3d4123456/article/details/52556193