LeetCode算法练习top100:(5)二叉树

java 复制代码
package top100.top二叉树;

import top100.TreeNode;

import java.util.*;

public class TOP {
    //94. 二叉树的中序遍历
    List<Integer> res = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        inorder(root);
        return res;
    }
    private void inorder(TreeNode root) {
        if (root != null) {
            inorder(root.left);
            res.add(root.val);
            inorder(root.right);
        }
    }


    //104. 二叉树的最大深度
    int maxDepth = 0;
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return maxDepth;
        }
        dfsMaxDepth(root, 0);
        return maxDepth;
    }
    private void dfsMaxDepth(TreeNode root, int res) {
        if (root == null) {
            maxDepth = Math.max(maxDepth, res);
        } else {
            dfsMaxDepth(root.left, res + 1);
            dfsMaxDepth(root.right, res + 1);
        }
    }


    //226. 翻转二叉树
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        TreeNode right = root.right;
        root.right = root.left;
        root.left = right;
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }


    //101. 对称二叉树
    public boolean isSymmetric(TreeNode root) {
        if (root == null) {
            return true;
        }
        return isSymmetric(root.left, root.right);
    }
    public boolean isSymmetric(TreeNode left, TreeNode right) {
        if (left == null && right == null) {
            return true;
        } else if (left == null || right == null) {
            return false;
        } else if (left.val != right.val) {
            return false;
        } else {
            return isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left);
        }
    }


    //543. 二叉树的直径
    int diameterOfBinaryTree = 0;
    public int diameterOfBinaryTree(TreeNode root) {
        dfsDiameterOfBinaryTree(root);
        return diameterOfBinaryTree;
    }
    //计算当前节点到其叶子节点的最长距离
    private int dfsDiameterOfBinaryTree(TreeNode root) {
        if (root == null) return 0;
        //左右节点的最长距离
        int l = dfsDiameterOfBinaryTree(root.left);
        int r = dfsDiameterOfBinaryTree(root.right);
        diameterOfBinaryTree = Math.max(diameterOfBinaryTree, l + r);
        return Math.max(l, r) + 1;
    }


    //102. 二叉树的层序遍历
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int n = queue.size();
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                TreeNode node = queue.poll();
                list.add(node.val);
                if (node.left != null) {
                    queue.add(node.left);
                }
                if (node.right != null) {
                    queue.add(node.right);
                }
            }
            res.add(list);
        }
        return res;
    }


    //108. 将有序数组转换为二叉搜索树
    public TreeNode sortedArrayToBST(int[] nums) {
        if (nums.length == 0) return null;
        int start = 0, mid = (nums.length - 1) / 2;
        TreeNode root = new TreeNode(nums[mid]); //二叉搜索树的根节点是中序遍历数组中间的数
        if (mid - start > 0) { //如果数组可以构成左子树
            root.left = sortedArrayToBST(Arrays.copyOfRange(nums, start, mid));
        }
        if (mid < nums.length - 1) { //如果数组可以构成右子树
            root.right = sortedArrayToBST(Arrays.copyOfRange(nums, mid + 1, nums.length));
        }
        return root;
    }


    //98. 验证二叉搜索树
    long preVal = Long.MIN_VALUE; //为了通过测试用例,设置比int最小还要小的值
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        //先判断左子树是否满足
        if (!isValidBST(root.left)) {
            return false;
        }
        //中序是否满足递增
        if (root.val <= preVal) {
            return false;
        }
        preVal = root.val; //更新pre值
        //判断又子树
        return isValidBST(root.right);
    }


    //230. 二叉搜索树中第K小的元素
    int res1;
    int k;
    ArrayList<Integer> list = new ArrayList<>();
    public int kthSmallest(TreeNode root, int k) {
        this.k = k;
        inOrder(root, k);
        return res1;
    }
    //中序遍历,从最小结点开始遍历:二叉搜索树的中序遍历为递增序列
    private void inOrder(TreeNode root, int k) {
        if (root == null) return;
        if (root.left != null) {
            inOrder(root.left, k);
        }
        list.add(root.val);
        if (list.size() == k) {
            res1 = root.val;
            return;
        }
        if (root.right != null) {
            inOrder(root.right, k);
        }
    }
    //230. 二叉搜索树中第K小的元素
    int res1;
    int k;
    public int kthSmallest(TreeNode root, int k) {
        this.k = k;
        inOrder(root);
        return res1;
    }
    private void inOrder(TreeNode root) {
        if (root == null) return;
        //先递归到左端点
        inOrder(root.left);
        if (k == 0) return;
        //遍历到第k个
        if (--k == 0) res1 = root.val;
        //中序遍历
        inOrder(root.right);
    }


    //199. 二叉树的右视图
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int n = queue.size();
            for (int i = 0; i < n; i++) {
                TreeNode cur = queue.poll();
                if (i == n - 1) {
                    res.add(cur.val);
                }
                if (cur.left != null) {
                    queue.add(cur.left);
                }
                if (cur.right != null) {
                    queue.add(cur.right);
                }
            }
        }
        return res;
    }


    //114. 二叉树展开为链表
    //方法1:逆前序遍历
    TreeNode preTreeNode = null;
    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }
        flatten(root.right);
        flatten(root.left);
        root.left = null;
        root.right = preTreeNode;
        preTreeNode = root;
    }
    //方法2:前序遍历后重组
    public void flatten(TreeNode root) {
        ArrayList<TreeNode> list = new ArrayList<>();
        preOder(root, list);
        for (int i = 1; i < list.size(); i++) {
            TreeNode pre = list.get(i - 1);
            TreeNode cur = list.get(i);
            pre.left = null;
            pre.right = cur;
        }
    }
    private void preOder(TreeNode root, ArrayList<TreeNode> list) {
        if (root != null) {
            list.add(root);
            if (root.left != null) {
                preOder(root.left, list);
            }
            if (root.right != null) {
                preOder(root.right, list);
            }
        }
    }


    //105. 从前序与中序遍历序列构造二叉树
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = preorder.length;
        if (n == 0) return null;
        TreeNode root = new TreeNode(preorder[0]);
        //获取根节点在中序的位置
        int mid = 0;
        for (int i = 0; i < n; i++) {
            if (inorder[i] == preorder[0]) {
                mid = i;
                break;
            }
        }
        //构造左右子树
        root.left = buildTree(Arrays.copyOfRange(preorder, 1, mid + 1), Arrays.copyOfRange(inorder, 0, mid));
        root.right = buildTree(Arrays.copyOfRange(preorder, mid + 1, preorder.length), Arrays.copyOfRange(inorder, mid + 1, inorder.length));
        return root;
    }


    //437. 路径总和 III
    int res4 = 0;
    //从每个节点dfs
    public int pathSum(TreeNode root, int targetSum) {
        if (root == null) return 0;
        //遍历每个节点 bfs
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int n = queue.size();
            for (int i = 0; i < n; i++) {
                TreeNode cur = queue.poll();
                dfs4(cur, targetSum);
                if (cur.left != null) queue.add(cur.left);
                if (cur.right != null) queue.add(cur.right);
            }
        }
        return res4;
    }
    private void dfs4(TreeNode root, long curSum) {
        if (root != null) {
            curSum -= root.val;
            if (curSum == 0) {
                res4++;
            }
            //递归
            dfs4(root.left, curSum);
            dfs4(root.right, curSum);
        }
    }


    //236. 二叉树的最近公共祖先
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left == null) return right;
        if(right == null) return left;
        return root;
    }


    //124. 二叉树中的最大路径和
    int res = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        dfs6(root);
        return res;
    }
    //计算root作为父结点所在在路径的最大路径和
    private int dfs6(TreeNode root) {
        if (root == null) return 0;
        //计算左子树的最大路径和,抛弃负数的路径
        int left = Math.max(0, dfs6(root.left));
        int right = Math.max(0, dfs6(root.right));
        //计算路径 left -> root -> right 的和
        res = Math.max(res, left + right + root.val);
        //返回root结点所在的子树最大路径和给父结点使用
        return root.val + Math.max(left, right);
    }
}
相关推荐
Source.Liu22 分钟前
【A11】 labelprinter(Tauri 版)新建步骤
windows·rust
WiChP40 分钟前
【V0.1B16】从零开始的2D游戏引擎开发之路
开发语言·算法·游戏引擎
番茄巴士1 小时前
手写一个 mini HashMap,彻底搞懂哈希表原理
算法
Punchline2781 小时前
解决 Windows 环境变量 Path 设置时提示“字符太长”的完整指南
windows·环境变量·path
圣保罗的大教堂2 小时前
leetcode 3742. 网格中得分最大的路径 中等
leetcode
宣宣猪的小花园.2 小时前
【机器学习】过拟合与泛化:模型为什么会“刷题很强、实战失灵”
人工智能·算法·机器学习
INGNIGHT2 小时前
624.数组列表中的最大距离(maximum)
算法·散列表
Niuguangshuo2 小时前
论文解读:w2v-BERT,把 wav2vec 2.0 和 BERT 合成一根管子的语音 SSL
算法·音视频·语音识别
科技小E2 小时前
国标视频分析平台EasyGBS×自动化AI算法训练服务器DLTM,把通用AI炼成你的现场AI
算法·自动化·音视频
zander2582 小时前
LeetCode 15. 三数之和
算法