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

news/2024/7/7 22:47:39
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);
    }
}


http://lihuaxi.xjx100.cn/news/1814647.html

相关文章

C进阶---文件操作

我们在日常使用电脑保存文件时&#xff0c;其目的就是为了便于以后查看、修改、更新等操作&#xff1b;保存在文件中可以使数据持久化&#xff0c;所以今天我们家里学习文件的相关操作。 一、文件 1.1什么是文件 磁盘上的文件是文件。 在程序设计中&#xff0c;文件一般分…

Ubuntu环境下基于libxl库文件使用C++实现对表格的操作

功能 表格不存在则创建后再进行操作创建sheet添加新的工作表在sheet中增加数据设置单元格样式 相关配置 下载地址&#xff1a;libxl选择 LibXL for Linux 4.2.0 i386 x64 armhf aarch64 安装配置 1&#xff0c;使用 tar zxvf 文件名.tar.gz 进行文件解压2&#xff0c;创…

开发盲盒商城的意义

开发盲盒商城的意义在于为电商行业带来新的增长机会&#xff0c;满足消费者对购物方式趣味性的需求&#xff0c;同时提升用户的参与度&#xff0c;为商家带来更多销售机会和增强影响力的机遇。 盲盒商城系统通过独特的盲盒玩法&#xff0c;为用户带来了全新的趣味购物体验&…

什么是主机安全,为什么我们需要主机安全。

什么是主机安全&#xff1a; 德迅主机安全基于德迅云安全积累的海量威胁数据&#xff0c;采用自适应安全架构&#xff0c;为用户提供远程保护、资产清点、黑客入侵检测、病毒查杀、漏洞风险发现预警及安全合规基线等安全防护服务&#xff0c;对当前服务器面临的主要网络安全风险…

[汇编实操]DOSBox工具安装——Ubuntu18.04系统

一、下载&安装 sudo apt install -y dosbox 二、启动 dosbox 三、C盘挂载 将上述文件下载放在任意路径&#xff0c;将DEBUG目录映射为虚拟C盘 MASM.EXE 是用来编译的&#xff0c;LINK.EXE 用来链接&#xff0c;这俩是必须的。 执行如下命令&#xff1a; mount c /m…

再谈谈注解

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 注解&#xff0c;和反射…

gzip 压缩优化大 XML 响应的处理方法

当处理大型XML响应时&#xff0c;我们经常会面临内存限制和性能问题。 在处理这个问题时&#xff0c;我们可以使用Python的requests库和lxml库来解决。下面是解决方案的步骤&#xff1a; 1. 使用requests库发送HTTP请求获取XML响应。 2. 检查响应的Content-Encoding标头&…