【LeetCode Hot100】二叉树篇

前言

        本文用于整理LeetCode Hot100中题目解答,因题目比较简单且更多是为了面试快速写出正确思路,只做简单题意解读和一句话题解方便记忆。但代码会全部给出,方便大家整理代码思路。


94. 二叉树的中序遍历

一句话题意

        返回二叉树中序遍历的数值数组。

一句话题解

        二叉树中序遍历是:先访问当前左节点,然后读取当前节点值,最后访问右节点。

        模拟即可。

class Solution {
    List<Integer> ans = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        dfs(root);
        return ans;
    }
    void dfs(TreeNode node){
        if(node == null) return ;
        dfs(node.left);
        ans.add(node.val);
        dfs(node.right);
    }
}

104. 二叉树的最大深度

一句话题意

        求二叉树最大深度。

一句话题解

        二叉树最大深度也就是从根节点到叶子节点最大距离,模拟即可。

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

226. 翻转二叉树

一句话题意

        将二叉树中每个左右节点进行反转。

一句话题解

        广搜然后模拟跑一下即可。

class Solution {
    public TreeNode invertTree(TreeNode root) {
        Queue<TreeNode> q = new LinkedList<>();
        if(root != null ) q.add(root);
        while(q.size() > 0){
            TreeNode x = q.poll();
            if(x==null)continue;
            TreeNode mid = x.left;
            x.left = x.right;
            x.right = mid;
            q.add(x.left);
            q.add(x.right); 
        }
        return root;
    }
}

101. 对称二叉树

一句话题意

        检查给定的二叉树是否根据根节点对称。

一句话题解

        模拟。

class Solution {
    public boolean check(TreeNode l, TreeNode r){
        if(l==null&&r==null)return true;
        if((r==null&&l!=null)||(r!=null&&l==null)||(l.val!=r.val))return false;
        return check(l.left,r.right)&check(l.right,r.left);
    } 
    public boolean isSymmetric(TreeNode root) {
        return check(root.left,root.right);
    }
}

543. 二叉树的直径

一句话题意

        求树上两点距离的最大值,即树的直径。

一句话题解

        当前节点的左子树最大深度+当前节点的右子树最大深度=以当前节点为中间点的最长链

class Solution {
    int ans;
    int dfs(TreeNode a){
        if(a==null)return 0;
        int l=dfs(a.left);
        int r=dfs(a.right);
        ans=Math.max(ans,l+r);
        return Math.max(l,r)+1;
    }
    public int diameterOfBinaryTree(TreeNode root) {
        dfs(root);
        return ans;
    }
}

102. 二叉树的层序遍历

一句话题意

        将二叉树进行层序遍历,将值保留在二维数组中。

一句话题解

        广搜层序遍历模拟即可。

class Solution {
    class Node {
        TreeNode node;
        int dep;
        Node(TreeNode node,int dep){
            this.node = node ;
            this.dep = dep;
        }
    }
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ans = new ArrayList<>();
        Queue<Node> q = new LinkedList<>();
        q.add(new Node(root,0));
        while(q.size()>0){
            Node x = q.poll();
            if(x.node==null)continue;
            if(ans.size()<=x.dep)ans.add(new ArrayList<>());
            ans.get(x.dep).add(x.node.val);
            q.add(new Node(x.node.left,x.dep+1));
            q.add(new Node(x.node.right,x.dep+1));
        }
        return ans;
    }
}

108. 将有序数组转换为二叉搜索树

一句话题意

        给定一个有序列表,将列表中的数据转化成一颗平衡二叉搜索树。

一句话题解

        平衡二叉搜索树 AVL树的特点是,当前节点的左节点的值要比当前节点小,右节点的值要比当前节点大。并且树不能连续三个左偏或右偏(因为可以进行转化)。根据上述特点,用二分来模拟建树即可。

class Solution {
    int[] arr;
    TreeNode dfs(TreeNode node ,int l,int r){
        if(l>r)return null;
        int mid=l+r>>1;
        node.val = arr[mid];
        node.left = dfs(new TreeNode(),l , mid-1);
        node.right = dfs(new TreeNode(), mid+1,r);
        return node;
    }
    public TreeNode sortedArrayToBST(int[] nums) {
        arr=nums;
        return dfs(new TreeNode(),0,nums.length-1);
    }
}

98. 验证二叉搜索树

一句话题意

        验证是否为二叉搜索树。

        有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。

  • 节点的右子树只包含 大于 当前节点的数。

  • 所有左子树和右子树自身必须也是二叉搜索树。

一句话题解

        方法一:按照题意模拟,验证即可。

        方法二:通过层序遍历,拿出数值数组,确保数值数组为递增序列即可验证时二叉搜索树。

class Solution {
    public boolean check(TreeNode node, long mn, long mx) {
        if (node == null)return true;
        if (node.val<= mn||node.val>=mx) return false;
        return check(node.left, mn, node.val) && check(node.right, node.val, mx);
    }
    public boolean isValidBST(TreeNode root) {
        return check(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }
}

230. 二叉搜索树中第 K 小的元素

一句话题意

        找到二叉搜索中第K小的元素。

一句话题解

        中序遍历跑一遍二叉搜索树,每次读取中间节点值得时候K--,最后K为0时候取值即可。

class Solution {
    int ans;
    int cnt;
    void dfs(TreeNode node){
        if(node==null||cnt==0)return ;
        dfs(node.left);
        cnt--;
        if(cnt==0)ans=node.val;
        dfs(node.right);
    }
    public int kthSmallest(TreeNode root, int k) {
        ans=-1;
        cnt=k;
        dfs(root);
        return ans;
    }
}

199. 二叉树的右视图

一句话题意

        给定一颗二叉树,求二叉树的每一层最右侧的节点。

一句话题解

        先序遍历二叉树,每次访问节点的时候更新当前层的节点。

class Solution {
    List<Integer> ans =new ArrayList<>();
    public List<Integer> rightSideView(TreeNode root) {
        dfs(root,0);
        return ans;
    }
    void dfs(TreeNode node ,int dep){
        if(node==null)return ;
        if(ans.size()<=dep)ans.add(node.val);
        else ans.set(dep,node.val);
        dfs(node.left, dep+1);
        dfs(node.right,dep+1);
    }
}

114. 二叉树展开为链表

一句话题意

        给定一颗二叉树,让这棵树变成一颗右偏树,展开后的链表的顺序应与先序遍历的顺序相同。不要使用额外空间。

一句话题解

        优先去访问左节点,当访问到当前左节点存在右节点的时候,将右节点的最后一个拿出来,连接到当前前节点的右节点上,这样能保证右侧的链先连接成功。然后处理左节点,将左节点练到前一个节点的右节点上,然后左节点置空即可。

class Solution {
    public void flatten(TreeNode root) {
        while(root!=null){
            if(root.left!=null){
                TreeNode x= root.left;
                TreeNode y = x;
                while(y.right!=null){
                    y=y.right;
                }
                y.right=root.right;
                root.left=null;
                root.right=x;
            }
            root=root.right;
        }
    }
}

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

一句话题意

        给定树的先序遍历和中序遍历,重新构建二叉树。

一句话题解

        先序遍历的数组的第一节点是根节点,中序遍历可以判断出来根节点的左子树和右子树节点个数。

        根据上面的两个特点,即可重新构造二叉树,即每次重复获取根节点,然后获取两侧个数,然后再去获取中间节点即可。用HashMap加速获取节点下表的速度。

class Solution {
    int[] pre;
    HashMap<Integer,Integer> mp=new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.pre=preorder;
        for(int i=0;i<inorder.length;i++){
            mp.put(inorder[i],i);
        }
        return build(0,0,inorder.length-1);
    }
    TreeNode build(int root,int l,int r){
        if(l>r)return null;
        TreeNode node=new TreeNode(pre[root]);
        int mid=mp.get(pre[root]);
        node.left=build(root+1,l,mid-1);
        node.right=build(root+mid-l+1,mid+1,r);//mid-l左子树节点个数
        return node;
    }
}

437. 路径总和 III

一句话题意

        求每个从父节点到父节点下面其中一个子节点的路径和为Target的路径个数。

一句话题解

        从上到下做树形前缀和。

class Solution {
    int ans=0;
    int target;
    HashMap<Long,Integer> mp = new HashMap<>();
    public int pathSum(TreeNode root, int targetSum) {
        this.target=targetSum;
        mp.put(0L,1);
        dfs(root,0);
        return ans;
    }
    void dfs(TreeNode node,long sum){
        if(node==null)return ;
        sum+=node.val;
        ans+=mp.getOrDefault(sum - target,0);
        mp.put(sum,mp.getOrDefault(sum,0)+1);
        dfs(node.left,sum);
        dfs(node.right,sum);
        mp.put(sum,mp.get(sum)-1);
    }
}

236. 二叉树的最近公共祖先

一句话题意

        求树任意两点的LCA。

一句话题解

        先把所有节点的所属层数求出,然后根据层次结构往上跑父亲节点就可以了。

class Solution {
    HashMap<Integer,Integer> deep;
    HashMap<Integer,TreeNode> fa;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        fa=new HashMap<Integer,TreeNode>();
        deep=new HashMap<Integer,Integer>();
        dfs(root,new TreeNode(-1),0);
        while(deep.get(p.val)>deep.get(q.val)){
            p=fa.get(p.val);
        }
        while(deep.get(p.val)<deep.get(q.val)){
            q=fa.get(q.val);
        }
        while(p.val!=q.val){
            p=fa.get(p.val);
            q=fa.get(q.val);
        }
        return p;
    }
    void dfs(TreeNode root,TreeNode faa,int dep){
        if(root==null)return ;
        deep.put(root.val,dep);
        fa.put(root.val,faa);
        dfs(root.left,root,dep+1);
        dfs(root.right,root,dep+1);
    }
}

124. 二叉树中的最大路径和

一句话题解

        求二叉树任意两点间距离的最大值。

一句话题解

        非常类似树的直接的思路,求当前节点左子树的最长链和右子树的最长链,加上自己本身,便是当前节点处于中点的最长路径。

class Solution {
    int ans = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        dfs(root);
        return ans;
    }
    int dfs(TreeNode node){
        if(node==null)return 0;
        int l = Math.max(dfs(node.left),0);
        int r = Math.max(dfs(node.right),0);
        ans=Math.max(ans,l+r+node.val);
        return node.val+Math.max(l,r);
    }
}

### LeetCode Hot 100 Problems 列表 LeetCode 的热门题目列表通常由社区投票选出,涵盖了各种难度级别的经典编程挑战。这些题目对于准备技术面试非常有帮助。以下是部分 LeetCode 热门 100 题目列表: #### 数组与字符串 1. **两数之和 (Two Sum)** 2. **三数之和 (3Sum)** 3. **无重复字符的最长子串 (Longest Substring Without Repeating Characters)** 4. **寻找两个正序数组的中位数 (Median of Two Sorted Arrays)** #### 动态规划 5. **爬楼梯 (Climbing Stairs)** 6. **不同的二叉搜索 (Unique Binary Search Trees)** 7. **最大子序列和 (Maximum Subarray)** #### 字符串处理 8. **有效的括号 (Valid Parentheses)** 9. **最小覆盖子串 (Minimum Window Substring)** 10. **字母异位词分组 (Group Anagrams)** #### 图论 11. **岛屿数量 (Number of Islands)** 12. **课程表 II (Course Schedule II)** #### 排序与查找 13. **最接近原点的 K 个点 (K Closest Points to Origin)** 14. **接雨水 (Trapping Rain Water)** 15. **最长连续序列 (Longest Consecutive Sequence)[^2]** #### 堆栈与队列 16. **每日温度 (Daily Temperatures)** 17. **滑动窗口最大值 (Sliding Window Maximum)** #### 结构 18. **验证二叉搜索 (Validate Binary Search Tree)** 19. **二叉树的最大路径和 (Binary Tree Maximum Path Sum)** 20. **从前序与中序遍历序列构造二叉树 (Construct Binary Tree from Preorder and Inorder Traversal)** #### 并查集 21. **冗余连接 II (Redundant Connection II)** #### 贪心算法 22. **跳跃游戏 (Jump Game)** 23. **分割等和子集 (Partition Equal Subset Sum)** #### 双指针技巧 24. **环形链表 II (Linked List Cycle II)[^1]** 25. **相交链表 (Intersection of Two Linked Lists)** #### 其他重要题目 26. **LRU缓存机制 (LRU Cache)** 27. **打家劫舍系列 (House Robber I & II)** 28. **编辑距离 (Edit Distance)** 29. **单词拆分 (Word Break)** 此列表并非官方发布版本而是基于社区反馈整理而成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值