二叉树面试题解析

二叉树面试题解析

判断相同的树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        // 不相同情况: 
        // 一个根为空 一个根不为空
        if (p == null && q != null || p != null && q == null) {
            return false;
        }
        // 走到这说明 两个根都为空 或者 都不为空
        // 如果都为空返回true,都不为空判断值
        if (p == null && q == null) {
            return true;
        }
        if (p.val != q.val) {
            return false;
        }
        // 走到这说明根相同 接下来判断左右子树是否相同
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }
}

另一颗树的子树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    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.val != q.val) {
            return false;
        }
        // 走到这说明根相同 接下来判断左右子树是否相同
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if (root == null) {
            return false;
        }
        // 判断根
        if (isSameTree(root,subRoot)) {
            return true;
        }
        // 判断左子树
        if(isSubtree(root.left,subRoot)) {
            return true;
        }
         // 判断右子树
        if(isSubtree(root.right,subRoot)) {
            return true;
        }
        return false;

    }
}

翻转二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        if (root.left == null && root.right == null) {
            return root;
        }
        
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        invertTree(root.left);
        invertTree(root.right);

        return root;
    }
}

 

二叉树的最大深度

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftHeight = maxDepth(root.left);
        int rightHeight = maxDepth(root.right);

        return leftHeight > rightHeight
            ? leftHeight+1 : rightHeight+1;

    }
}

会遍历树中所有的节点,时间复杂度为O(N)

判断平衡二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        // 如何判断是否是平衡二叉树
        // 当前根节点左右子树高度差<=1, 左子树平衡 && 右子树平衡
        if (root == null) {
            return true;
        }
        int leftTH = maxDepth(root.left);
        int rightTH = maxDepth(root.right);
        return Math.abs(leftTH - rightTH) <= 1
            && isBalanced(root.left) && isBalanced(root.right);


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

        return leftHeight > rightHeight
            ? leftHeight+1 : rightHeight+1;

    }
}

每一个节点都会去计算高度,n(节点个数) × n(计算一次高度的时间复杂度) = O(n^2)

能否以O(N) 时间复杂度解题 ?

可以, 在计算高度的同时 判断是否平衡

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftHeight = maxDepth(root.left);
        if (leftHeight == -1) {
            return -1;
        }
        int rightHeight = maxDepth(root.right);
        if (leftHeight >= 0 && rightHeight >= 0 && 
            Math.abs(leftHeight-rightHeight) <= 1) {
            return Math.max(leftHeight,rightHeight)+1;
        }else {
            return -1;
        }
    }

    public boolean isBalanced(TreeNode root) {
        // 计算高度的同时判断是否平衡
        if (root == null) {
            return true;
        }
        return maxDepth(root) != -1;
    }
    
}

 

判断对称二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return isSymmetricChild(root.left,root.right);
    }
    public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree) {
        // 一个为空 一个不为空 ———— 不对称
        if (leftTree == null && rightTree != null) {
            return false;
        }
        if (leftTree != null && rightTree == null) {
            return false;
        }
        if (leftTree == null && rightTree == null) {
            return true;
        }
        if (leftTree.val != rightTree.val) {
            return false;
        }
        // 走到这说明根对称, 然后接下来判断 
        // 左子树的左——右子树的右 && 左子树的右——右子树的左 是否对称
        return isSymmetricChild(leftTree.left,rightTree.right) 
            && isSymmetricChild(leftTree.right,rightTree.left);


    }
}

 

前序遍历创建二叉树

import java.util.Scanner;

class TreeNode {
    public char val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(char val) {
        this.val = val;
    }
}

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static int i;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String str = in.nextLine();

            // 根据输入的前序遍历创建树
            TreeNode root = createTree(str);

            // 中序遍历
            inOrder(root);

        }
    }
    public static TreeNode createTree(String str) {
        TreeNode root = null;
        if (str.charAt(i) != '#') {
            root = new TreeNode(str.charAt(i));
            i++;
            root.left = createTree(str);
            root.right = createTree(str);
        }else {
            i++;
        }
        return root;
    }
    public static void inOrder(TreeNode root) {
        // 左根右
        if (root == null) {
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }
}

 

二叉树的层序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {      
        List<List<Integer>> ret = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        if (root == null) {
            return ret;    
        }
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> array = new ArrayList<>();
            int size = queue.size();

            while (size != 0) {
                TreeNode cur = queue.poll();
                array.add(cur.val);
                size--;

                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            ret.add(array);
        }
        return ret;
    }
}

 

二叉树的最近公共祖先

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return null;
        }
        if (root == p || root == q) {
            return root;
        }
 
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);

        if (left != null && right != null) {
            return root;
        }else if(left != null) {
            return left;
        }else {
            return right;
        }

    }
}

 

这道题还有一个很有意思的题解

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    // 得到root -> node路径上所有节点
    public boolean getPathNode(TreeNode root,TreeNode node,Stack<TreeNode> stack) {
        if (root == null || node == null) {
            return false;
        }
        stack.push(root);
        if (root == node) {
            return true;
        }
        boolean leftFlag = getPathNode(root.left,node,stack);
        if (leftFlag == true) {
            return true;
        }

        boolean rightFlag = getPathNode(root.right,node,stack);
        if (rightFlag == true) {
            return true;
        }
        stack.pop();
        return false;

    }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        Stack<TreeNode> stackP = new Stack<>();
        Stack<TreeNode> stackQ = new Stack<>();
        getPathNode(root,p,stackP);
        getPathNode(root,q,stackQ);

        int sizeP = stackP.size();
        int sizeQ = stackQ.size();
        if (sizeP > sizeQ) {
            int gap = sizeP - sizeQ;
            while (gap != 0) {
                stackP.pop();
                gap--;
            } 
        }else {
            int gap = sizeQ - sizeP;
            while (gap != 0) {
                stackQ.pop();
                gap--;
            } 
        }

        while (!stackP.isEmpty() && !stackQ.isEmpty()) {
            TreeNode nodeP = stackP.pop();
            TreeNode nodeQ = stackQ.pop(); 
            if (nodeP == nodeQ) {
                return nodeP;
            }
        } 
        return null;
    }
}

从前序与中序遍历序列构造二叉树

解这道题的重点:

左子树 = [0, rootindex - 1] 

右子树 = [rootindex+1, inend] 

 

力扣通过代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int preIndex ;
    public TreeNode buildTree(int[] preorder, int[] inorder) {

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

    }
     private TreeNode buildTreeChild(int[] preorder,int[] inorder,int inbegin,int inend) {
        
        if (inbegin > inend) {
            return null;
        }
        
        TreeNode root = new TreeNode(preorder[this.preIndex]);
        int rootIndex = findIndexRoot(inorder,0,inorder.length,root.val);
        this.preIndex++;

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

        return root;
    }
    private int findIndexRoot(int[] inorder,int inbegin, int inend,int key) {
        for (int i = inbegin;i < inend;i++) {
            if (inorder[i] == key) {
                return i;
            }
        }
        return -1;
    }
}

 

测试代码:

public class SolutionCreateTree {

    static class TreeNode {
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }

    public int preIndex ;

    public TreeNode buildTree(char[] preorder, char[] inorder) {

        return buildTreeChild(preorder,inorder,0,inorder.length);

    }

    private TreeNode buildTreeChild(char[] preorder,char[] inorder,int inbegin,int inend) {
        if (inbegin > inend) {
            return null;
        }
        TreeNode root = new TreeNode(preorder[this.preIndex]);

        int rootIndex = findIndexRoot(inorder,0,inorder.length,root.val);
        this.preIndex++;

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

        return root;
    }

    private int findIndexRoot(char[] inorder,int inbegin, int inend,int key) {
        for (int i = inbegin;i < inend;i++) {
            if (inorder[i] == key) {
                return i;
            }
        }
        return -1;
    }
}
public class Test {
    public static void main(String[] args) {
        SolutionCreateTree  solutionCreateTree = new SolutionCreateTree();
        char[] preorder = {'E','F','H','I','G','J','K'};
        char[] inorder = {'H','F','I','E','J','K','G'};
        SolutionCreateTree.TreeNode root = solutionCreateTree.buildTree(preorder,inorder);
    }
}

 图解:

https://github.com/znxcmakhsd/DS/blob/main/12-29

 

从中序与后序遍历序列构造二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    /*static class TreeNode {
        public int val;
        public TreeNode left;
        public TreeNode right;
        public TreeNode(int val) {
            this.val = val;
        }
    }*/

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

    public TreeNode buildTreeChild(int[] inorder, int[] postorder,int inBegin,int inEnd) {
        if (inBegin > inEnd) {
            return null;
        }
        TreeNode root = new TreeNode(postorder[postIndex]);
        int rootIndex = findRootIndex(inorder,inBegin,inEnd,root.val);
        this.postIndex--;
        root.right = buildTreeChild(inorder,postorder,rootIndex+1,inEnd);
        root.left = buildTreeChild(inorder,postorder,inBegin,rootIndex-1);
        return root;
    }
    public int findRootIndex(int[] inorder,int inBegin,int inEnd,int key) {
        for (int i = inBegin;i <= inEnd;i++) {
            if (inorder[i] == key) {
                return i;
            }
        }
        return -1;
    }
}

 

根据二叉树创建字符串

力扣通过代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public String tree2str(TreeNode root) {
        StringBuilder stringBuilder = new StringBuilder();
        buildString(root,stringBuilder);
        return stringBuilder.toString();
    }
    public void buildString(TreeNode root,StringBuilder stringBuilder) {
        if (root == null) {
            return;
        }
        stringBuilder.append(root.val);
        if (root.left != null) {
            stringBuilder.append("(");
            buildString(root.left,stringBuilder);
            stringBuilder.append(")");
        }else {
            // 两种情况:
            // 1. 左右都为空
            if (root.right == null) {
                return;
            }else {
                // 2. 左为空 右不为空
                stringBuilder.append("()");
            }
        }
        if (root.right != null) {
            stringBuilder.append("(");
            buildString(root.right,stringBuilder);
            stringBuilder.append(")");
        }else {
            // 右边为空 直接返回
            return;
        }
    }
}

测试代码:

public class Solution {
    static class TreeNode {
        public int val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(int val) {
            this.val = val;
        }
    }

    public TreeNode createTree1() {
        TreeNode A = new TreeNode(1);
        TreeNode B = new TreeNode(2);
        TreeNode C = new TreeNode(3);
        TreeNode D = new TreeNode(4);
        A.left = B;
        A.right = C;
        B.left = D;
        return A;
    }

    public TreeNode createTree2() {
        TreeNode A = new TreeNode(1);
        TreeNode B = new TreeNode(2);
        TreeNode C = new TreeNode(3);
        TreeNode D = new TreeNode(4);
        A.left = B;
        A.right = C;
        B.right = D;
        return A;
    }

    public String tree2str(TreeNode root) {
        StringBuilder stringBuilder = new StringBuilder();
        tree2strChild(root, stringBuilder);
        return stringBuilder.toString();
    }

    private void tree2strChild(TreeNode t, StringBuilder stringBuilder) {
        if (t == null) {
            return;
        }
        stringBuilder.append(t.val);
        if (t.left != null) {
            stringBuilder.append("(");
            tree2strChild(t.left, stringBuilder);
            stringBuilder.append(")");
        } else {
            if (t.right == null) {
                return;
            } else {
                stringBuilder.append("()");
            }
        }
        //判断右树
        if (t.right != null) {
            stringBuilder.append("(");
            tree2strChild(t.right, stringBuilder);
            stringBuilder.append(")");
        } else {
            return;
        }
    }
    public static void main(String[] args) {

        Solution solution = new Solution();
        Solution.TreeNode root1 = solution.createTree1();
        Solution.TreeNode root2 = solution.createTree2();
        solution.tree2str(root2);


    }
}

 

递归实现:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) {
            return list;
        }

        list.add(root.val);

        List<Integer> leftTree = preorderTraversal(root.left);
        list.addAll(leftTree);

        List<Integer> rightTree = preorderTraversal(root.right);
        list.addAll(rightTree);

        return list;
    }
}

 

posted @ 2023-12-31 13:43  qyx1  阅读(26)  评论(0)    收藏  举报