二叉树

二叉树

BM23 二叉树的前序遍历

public class Solution {
    List<Integer> list = new ArrayList<>();
    public int[] preorderTraversal (TreeNode root) {
        orderTraversal(root);
        int[] arr = new int[list.size()];
        int i = 0;
        for(Integer each : list) arr[i++] = each;
        return arr;
    }
    
    public void orderTraversal(TreeNode root){
        if(root == null) return;
	/****************前序遍历*******************/
        list.add(root.val);
        orderTraversal(root.left);
        orderTraversal(root.right);
	/*******************************************/
    }
}

BM24 二叉树的中序遍历

public class Solution {
    List<Integer> list = new ArrayList<>();
    public int[] inorderTraversal (TreeNode root) {
        orderTraversal(root);
        int[] arr = new int[list.size()];
        int i = 0;
        for(Integer each : list) arr[i++] = each;
        return arr;
    }
    
    public void orderTraversal(TreeNode root){
        if(root == null) return;
	/****************中序遍历*******************/
        orderTraversal(root.left);
        list.add(root.val);
        orderTraversal(root.right);
	/*******************************************/
    }
}

BM25 二叉树的后序遍历

public class Solution {
    List<Integer> list = new ArrayList<>();
    public int[] inorderTraversal (TreeNode root) {
        orderTraversal(root);
        int[] arr = new int[list.size()];
        int i = 0;
        for(Integer each : list) arr[i++] = each;
        return arr;
    }
    
    public void orderTraversal(TreeNode root){
        if(root == null) return;
	/****************后序遍历*******************/
        orderTraversal(root.left);
        orderTraversal(root.right);
        list.add(root.val);
	/*******************************************/
    }
}

BM26 二叉树的层序遍历

public class Solution {
    // BFS算法
    ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
        if(root == null) return res;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            ArrayList<Integer> list = new ArrayList<>();
            int size = queue.size();
            for(int i = 0; i < size; i++){
                TreeNode node = queue.poll();
                list.add(node.val);
                if(node.left != null) queue.offer(node.left);
                if(node.right != null) queue.offer(node.right);
            }
            res.add(list);
        }
        return res;
    }
}

BM27 按之字形顺序打印二叉树

public class Solution {
    ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    public ArrayList<ArrayList<Integer>> Print (TreeNode root) {
        if(root == null) return res;
        /********************注意!!!采用双向链表*******************************/
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        // 分层遍历,level用于标记层数
        int level = 1;
        while(!queue.isEmpty()){
            ArrayList<Integer> list = new ArrayList<>();
            int size = queue.size();
            if((level & 1) == 1){// 奇数层
                for(int i = 0; i < size; i++){
                    /*******************奇数层从后面取节点************************/
                    TreeNode node = queue.removeLast();
                    list.add(node.val);
                    /*******************奇数层先加左后加右***********************/
                    if(node.left != null) queue.addFirst(node.left);
                    if(node.right != null) queue.addFirst(node.right);
                }
            }else{// 偶数层
                for(int i = 0; i < size; i++){
                    /********************偶数层从前面取节点**********************/
                    TreeNode node = queue.removeFirst();
                    list.add(node.val);
                    /********************偶数层先加右后加左**********************/
                    if(node.right != null) queue.addLast(node.right);
                    if(node.left != null) queue.addLast(node.left);
                }
            }
            level++;
            res.add(list);
        }
        return res;
    }
}

BM28 二叉树的最大深度

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

BM29 二叉树中和为某一值的路径(一)

public class Solution {
    public boolean hasPathSum (TreeNode root, int sum) {
        if(root == null) return false;
        sum -= root.val;
        // 到达叶子结点
        if(sum == 0 && root.left == null && root.right == null) return true;
        // 递归左右子树
        return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
    }
}

BM30 二叉搜索树与双向链表(注意)

方法一:非递归版
	解题思路:
	1.核心是中序遍历的非递归算法。
	2.修改当前遍历节点与前一遍历节点的指针指向。
import java.util.Stack;
public class Solution {
    // 方法一:中序遍历的非递归算法
    public TreeNode Convert(TreeNode root) {
        if(root == null) return null;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode p = root;
        TreeNode pre = null;// 用于保存中序遍历序列的上一节点
        boolean isFirst = true;
        while(p != null || !stack.isEmpty()){
            while( p != null){
                stack.push(p);
                p = p.left;
            }
            p = stack.pop();
            if(isFirst){
                root = p;// 将中序遍历序列中的第一个节点记为root
                pre = root;
                isFirst = false;
            }else{
                pre.right = p;
                p.left = pre;
                pre = p;
            }      
            p = p.right;
        }
        return root;
    }
}
方法二:递归版
	解题思路:
	1.将左子树构造成双链表,并返回链表头节点。
	2.定位至左子树双链表最后一个节点。
	3.如果左子树链表不为空的话,将当前root追加到左子树链表。
	4.将右子树构造成双链表,并返回链表头节点。
	5.如果右子树链表不为空的话,将该链表追加到root节点之后。
	6.根据左子树链表是否为空确定返回的节点。
public class Solution {
    // 记录子树链表的最后一个节点,终结点只可能为只含左子树的非叶节点与叶节点
    protected TreeNode leftLast = null;
    public TreeNode Convert(TreeNode root) {
        if(root == null) return null;
        if(root.left == null && root.right == null){
            leftLast = root;// 最后的一个节点可能为最右侧的叶节点
            return root;
        }
        // 1.将左子树构造成双链表,并返回链表头节点
        TreeNode left = Convert(root.left);
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表
        if(left != null){
            leftLast.right = root;
            root.left = leftLast;
        }
        leftLast = root;// 当根节点只含左子树时,则该根节点为最后一个节点
        // 4.将右子树构造成双链表,并返回链表头节点
        TreeNode right = Convert(root.right);
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后
        if(right != null){
            right.left = root;
            root.right = right;
        }
        return left != null ? left : root;
    }
}

BM31 对称的二叉树

public class Solution {
    boolean isSymmetrical(TreeNode pRoot) {
        // 根节点为null
        if(pRoot == null) return true;
        // 判断左右子树是否对称
        return isSymmetrical(pRoot.left, pRoot.right);
    }
    
    boolean isSymmetrical(TreeNode root1, TreeNode root2) {
        // 两个子树均为null
        if(root1 == null && root2 == null) return true;
        // 其中一个子树为null
        if(root1 == null || root2 == null) return false;
        // 左右子节点不相等
        if(root1.val != root2.val) return false;
        
        return isSymmetrical(root1.right, root2.left) && isSymmetrical(root1.left, root2.right);
    }
}

BM32 合并二叉树

public class Solution {
    public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {
        // 合并到t1中,输出t1子树
        // 若t1和t2均为null,则返回null
        if(t1 == null && t2 == null) return null;
        // 若t1为null,则返回t2
        // 若t2为null,则返回t1
        if(t1 == null) return t2;
        if(t2 == null) return t1;
        // 若t1和t2均不为null,则合并值
        t1.val += t2.val;
        
        // 继续合并左右子树
        t1.left = mergeTrees(t1.left, t2.left);
        t1.right = mergeTrees(t1.right, t2.right);
        
        return t1;
    }
}

BM33 二叉树的镜像

public class Solution {
    public TreeNode Mirror (TreeNode pRoot) {
        // 空节点,无需转换
        if(pRoot == null) return null;
        // 继续转换左右子树
        pRoot.left = Mirror(pRoot.left);
        pRoot.right = Mirror(pRoot.right);
        // 交换左右子树
        TreeNode node = pRoot.right;
        pRoot.right = pRoot.left;
        pRoot.left = node;
        return pRoot;
    }
}

BM34 判断是不是二叉搜索树

public class Solution {
    public boolean isValidBST (TreeNode root) {
        // 空节点,返回true
        if(root == null) return true;
        // 单节点,返回true
        if(root.left == null && root.right == null) return true;
        // 左子树为null,并且根节点的值小于右节点的值,则取决于右子树
        if(root.left == null && root.right.val > root.val) return isValidBST(root.right);
        // 右子树为null,并且根节点的值大于左节点的值,则取决于左子树
        if(root.right == null && root.left.val < root.val) return isValidBST(root.left);
        // 左右子树均不为null
        if(root.left.val > root.val || root.right.val < root.val) return false;
        // 判断前驱节点是否小于根节点,后继节点是否大于根节点
        return maxLeftTree(root.left, Integer.MIN_VALUE) < root.val && minRightTree(root.right, Integer.MAX_VALUE) > root.val;
    }
    
    public int maxLeftTree(TreeNode root, int ans){
        if(root == null) return ans;
        while(root.right != null){
            root = root.right;
            ans = Math.max(ans, root.val);
        }
        return ans;
    }
    
    public int minRightTree(TreeNode root, int ans){
        if(root == null) return ans;
        while(root.left != null){
            root = root.left;
            ans = Math.max(ans, root.val);
        }
        return ans;
    }
}

BM35 判断是不是完全二叉树

public class Solution {
    public boolean isCompleteTree (TreeNode root) {
        // 对于完全二叉树的结束位置前的所有节点一定非null
        if(root == null) return true;
        // BFS算法
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        // 标记是否结束
        boolean end = false;
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i = 0; i < size; i++){
                TreeNode node = queue.poll();
                if(node == null) {
                    // 修改状态,跳过本次循环
                    end = true;
                    continue;
                }
                // 如果再次进入循环,说明当前为null的节点并非结束,则该树不是完全二叉树
                if(end) return false;
                queue.offer(node.left);
                queue.offer(node.right);
            }
        }
        return true;
    }
}

BM36 判断是不是平衡二叉树

public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        if(root == null) return true;
        // 计算左右子树的最大深度
        int leftDepth = maxDepth(root.left);
        int rightDepth = maxDepth(root.right);
        // 若高度差大于1,则非平衡二叉树
        if(Math.abs(leftDepth - rightDepth) > 1) return false;
        // 判断左右子树是否为平衡二叉树
        return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
    }
    
    // 用以计算树的最大深度
    public int maxDepth(TreeNode root){
        if(root == null) return 0;
        return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
    }
}

BM37 二叉搜索树的最近公共祖先

public class Solution {
    public int lowestCommonAncestor (TreeNode root, int p, int q) {
        // 统一p为小值,q为大值
        if(p > q){// 交换p和q
            p = p ^ q;
            q = p ^ q;
            p = p ^ q;
        }
        if(p <= root.val && q >= root.val) return root.val;
        if(q < root.val) return lowestCommonAncestor(root.left, p, q);
        return lowestCommonAncestor(root.right, p, q);
    }
}

BM38 在二叉树中找到两个节点的最近公共祖先

public class Solution {
/*****************************时间复杂度很高***************************************/
//     public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
//         // 若根节点与其中一个值相等,则为最近公共祖先
//         if(root.val == o1 || root.val == o2) return root.val;
//         // 若两个值均在左子树中,则最近公共祖先在左子树中
//         if(search(root.left, o1) && search(root.left, o2)) return lowestCommonAncestor(root.left, o1, o2);
//         // 若两个值均在右子树中,则最近公共祖先在右子树中
//         if(search(root.right, o1) && search(root.right, o2)) return lowestCommonAncestor(root.right, o1, o2);
//         // 一个值在左子树,一个值在右子树,则根节点即为最近公共祖先
//         return root.val;
//     }
    
//     // 查找目标值
//     public boolean search(TreeNode root, int target){
//         if(root == null) return false;
//         if(root.val == target) return true;
//         return search(root.left, target) || search(root.right, target);
//     }
    

/*****************************时间复杂度较低***************************************/    
    public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // 若没找到任意一个值,则返回不存在-1
        if(root == null) return -1;
        // 若根节点与其中一个值相等,则返回当前值
        if(root.val == o1 || root.val == o2) return root.val;
        // 在左子树中查找
        int left = lowestCommonAncestor(root.left, o1, o2);
        // 在右子树中查找
        int right = lowestCommonAncestor(root.right, o1, o2);
        // 一个值在左子树,一个值在右子树,则根节点即为最近公共祖先
        if(left != -1 && right != -1) return root.val;
        // 否则,两个都在左子树中,或者两个都在右子树中
        // 若两个都在左子树中,则返回右子树中找到的值;若两个都在右子树中,则返回左子树中找到的值
        return left == -1 ? right : left;
    }
}

BM39 序列化二叉树

import java.util.*;
public class Solution {
    private static String SPLIT = ",";
    private static String NULL = "#";
    String Serialize(TreeNode root) {
        // 采用动态字符串存储序列化字符串
        StringBuilder str = new StringBuilder();
        // 序列化
        Serialize(root, str);
        // 将动态字符串转化为字符串
        return str.toString();
    }
    
    void Serialize(TreeNode root, StringBuilder str){
        if(root == null) {
            str.append(NULL).append(SPLIT);
            return;
        }
        /*******************前序遍历位置************************/
        str.append(root.val).append(SPLIT);
        Serialize(root.left, str);
        Serialize(root.right, str);
    }
    
    
    TreeNode Deserialize(String str) {
        // 将字符串转化为链表
        LinkedList<String> nodes = new LinkedList<>();
        for(String s : str.split(SPLIT)){
            nodes.addLast(s);
        }
        // 反序列化
        return Deserialize(nodes);
    }
    
    TreeNode Deserialize(LinkedList<String> nodes){
        if(nodes.isEmpty()) return null;
        /*******************前序遍历位置************************/
        // 链表最左边的就是根节点
        String first = nodes.removeFirst();
        if(first.equals(NULL)) return null;
        // 构建根节点
        TreeNode root = new TreeNode(Integer.parseInt(first));
        // 构建左右子树
        root.left = Deserialize(nodes);
        root.right = Deserialize(nodes);
        return root;
    }
}

BM40 重建二叉树

public class Solution {
    HashMap<Integer, Integer> map = new HashMap<>();
    public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
        if(pre.length == 0) return null;
        if(pre.length == 1) return new TreeNode(pre[0]);
        // 将vin中的索引存储在map中,方便查找根节点的位置
        for(int i = 0; i < vin.length; i++){
            map.put(vin[i], i);
        }
        // 构建二叉树
        return reConstructBinaryTree(pre, 0, pre.length - 1, vin, 0, vin.length - 1);
    }
    
    public TreeNode reConstructBinaryTree(int[] pre, int preStart, int preEnd, int[] vin, int inStart, int inEnd) {
        if(preStart > preEnd || inStart > inEnd) return null;
        // 构建根节点
        TreeNode root = new TreeNode(pre[preStart]);
        // 查找根节点在中序遍历数组中的索引位置
        int index = map.get(pre[preStart]);
        // 构建左子树,注意确定索引位置,index - inStart 为左子树的长度
        root.left = reConstructBinaryTree(pre, preStart + 1, preStart + index - inStart, vin, inStart, index - 1);
        // 构建右子树
        root.right = reConstructBinaryTree(pre, preStart + index - inStart + 1, preEnd, vin, index + 1, inEnd);
        return root;
    }
}

BM41 输出二叉树的右视图

import java.util.*;
public class Solution {
    List<Integer> res = new ArrayList<>();// 用于层序遍历
    HashMap<Integer, Integer> map = new HashMap<>();
    public int[] solve (int[] xianxu, int[] zhongxu) {
        if(xianxu.length == 0) return null;
        if(xianxu.length == 1) return xianxu;
        // 构建二叉树
        for(int i = 0; i < zhongxu.length; i++){
            map.put(zhongxu[i], i);
        }
        TreeNode root = reConstructBinaryTree(xianxu, 0, xianxu.length - 1, zhongxu, 0, zhongxu.length - 1);
        
        /*************************层序遍历****************************/
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            // 记录每一层的最后一个节点值
            int number = 0;
            int size = queue.size();
            for(int i = 0; i < size; i++){
                TreeNode node = queue.poll();
                number = node.val;// 更新number
                if(node.left != null) queue.offer(node.left);
                if(node.right != null) queue.offer(node.right);
            }
            // 将每一层的最后一个节点值放入链表
            res.add(number);
        }
        // 将链表中的值迁移到数组
        int[] nums = new int[res.size()];
        int i = 0;
        for(Integer num : res) nums[i++] = num;
        /************************************************************/
        
        // 返回结果
        return nums;
    }
    
    public TreeNode reConstructBinaryTree(int[] pre, int preStart, int preEnd, int[] vin, int inStart, int inEnd) {
        if(preStart > preEnd || inStart > inEnd) return null;
        // 构建根节点
        TreeNode root = new TreeNode(pre[preStart]);
        // 查找根节点在中序遍历数组中的索引位置
        int index = map.get(pre[preStart]);
        // 构建左子树,注意确定索引位置,index - inStart 为左子树的长度
        root.left = reConstructBinaryTree(pre, preStart + 1, preStart + index - inStart, vin, inStart, index - 1);
        // 构建右子树
        root.right = reConstructBinaryTree(pre, preStart + index - inStart + 1, preEnd, vin, index + 1, inEnd);
        
        return root;
    }
}
全部评论

相关推荐

牛客5655:其他公司的面试(事)吗
点赞 评论 收藏
分享
投票
我要狠拿offer:如果不是必须去成都绝对选九院呀,九院在四川top1研究所了吧
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务