LeetCode之二叉树

104. 二叉树的最大深度

/**
 * 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 {

    /**
     * 此方法用于计算给定二叉树的最大深度
     *
     * @param root 二叉树的根节点
     * @return 二叉树的最大深度值
     */
    public int maxDepth(TreeNode root) {
        // 如果根节点为空,说明树为空,返回深度 0
        if (root == null) {
            return 0;
        } else {
            // 递归计算左子树的深度
            int leftHeight = maxDepth(root.left);
            // 递归计算右子树的深度
            int rightHeight = maxDepth(root.right);
            // 取左子树和右子树深度中的最大值,并加上根节点这一层,得到整棵树的最大深度
            return Math.max(leftHeight, rightHeight) + 1;
        }

    }

}

100. 相同的树

/**
 * 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 {

    /**
     * 判断两棵二叉树是否相同
     *
     * @param p 第一棵二叉树的根节点
     * @param q 第二棵二叉树的根节点
     * @return 如果两棵树相同返回 true,否则返回 false
     */
    public boolean isSameTree(TreeNode p, TreeNode q) {
        // 如果两棵树的根节点都为空,说明两棵树相同,返回 true
        if (p == null && q == null) {
            return true;

        // 如果其中一棵树的根节点为空,另一棵不为空,说明两棵树不同,返回 false   
        } else if (p == null || q == null) {
            return false;

        // 如果两棵树的根节点值不同,说明两棵树不同,返回 false   
        } else if (p.val != q.val) {
            return false;
        } else {
            // 递归判断两棵树的左子树和右子树是否相同,只有都相同,两棵树才相同
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
        }
    }
}

226. 翻转二叉树

/**
 * 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 {

    /**
     * 翻转二叉树的函数

     * @param root 二叉树的根节点
     * @return 翻转后的二叉树根节点
     */
    public TreeNode invertTree(TreeNode root) {
        // 如果根节点为空,直接返回空
        if (root == null) {
            return null;
        }
        // 递归翻转左子树,并将结果保存到 left 变量
        TreeNode left = invertTree(root.left);
        // 递归翻转右子树,并将结果保存到 right 变量
        TreeNode right = invertTree(root.right);
        // 将右子树设置为原来的左子树
        root.right = left;
        // 将左子树设置为原来的右子树
        root.left = right;
        // 返回翻转后的根节点
        return root;
    }

}

101. 对称二叉树

/**
 * 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 {

    /**
     * 判断给定的二叉树是否对称
     *
     * @param root 二叉树的根节点
     * @return 如果二叉树对称返回 true,否则返回 false
     */
    public boolean isSymmetric(TreeNode root) {
        // 调用内部的 check 方法来进行对称性的检查,传入两个相同的根节点
        return check(root, root);
    }

    /**
     * 内部用于检查两棵子树是否对称的方法
     *
     * @param p 第一棵子树的根节点
     * @param q 第二棵子树的根节点
     * @return 如果两棵子树对称返回 true,否则返回 false
     */
    private boolean check(TreeNode p, TreeNode q) {
        // 如果两棵子树的根节点都为空,说明这部分对称,返回 true
        if (p == null && q == null) {
            return true;
        }
        // 如果其中一棵子树的根节点为空,另一棵不为空,说明不对称,返回 false
        if (p == null || q == null) {
            return false;
        }
        // 如果两棵子树根节点的值相等,并且左子树和右子树分别对称,返回 true
        return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);

    }
}

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

/**
 * 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 {
    private Map<Integer, Integer> indexMap; // 哈希表用于存储中序遍历中节点值与索引的对应关系

    // 递归构建树的核心方法
    public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        // 如果左边界大于右边界,说明没有节点可建,返回 null
        if (preorder_left > preorder_right) {
            return null;
        }

        // 前序遍历中的第一个节点就是根节点
        int preorder_root = preorder_left;
        // 在中序遍历中定位根节点的索引
        int inorder_root = indexMap.get(preorder[preorder_root]);

        // 根据根节点的值创建树节点
        TreeNode root = new TreeNode(preorder[preorder_root]);
        // 得到左子树中的节点数目
        int size_left_subtree = inorder_root - inorder_left;

        // 递归构造左子树,并连接到根节点
        // 先序遍历中「从左边界+1开始的size_left_subtree个元素」对应中序遍历中「从左边界开始到根节点定位-1的元素」
        root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);

        // 递归构造右子树,并连接到根节点
        // 先序遍历中「从左边界+1+左子树节点数目开始到右边界」的元素对应中序遍历中「从根节点定位+1到右边界的元素」
        root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);

        return root; // 返回构建的树节点
    }

    // 主方法,构建二叉树
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = preorder.length; // 获取节点总数
        // 构造哈希映射,帮助快速定位根节点在中序遍历中的索引
        indexMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < n; i++) {
            indexMap.put(inorder[i], i); // 存储中序遍历中的节点值及其索引
        }
        // 调用递归方法构建树,初始边界为整个数组
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
    }

}

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

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        // 调用深度优先搜索方法开始构建二叉树
        return dfs(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
    }

    private TreeNode dfs(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) {
        // 如果中序遍历区间或后序遍历区间无效,返回 null,表示无法构建子树
        if (inStart > inEnd || postStart > postEnd) {
            return null;
        }
        // 从后序遍历数组的末尾获取当前子树的根节点值
        int rootval = postorder[postEnd];
        // 创建根节点
        TreeNode root = new TreeNode(rootval);
        // 在中序遍历数组中找到根节点的位置
        int rootIndex = 0;
        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == rootval) {
                rootIndex = i;
                break;
            }
        }
        // 计算左子树的节点数量
        int leftSize = rootIndex - inStart;
        // 递归构建左子树,左子树的中序遍历区间为 [inStart, rootIndex - 1],后序遍历区间为 [postStart, postStart + leftSize - 1]
        root.left = dfs(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + leftSize - 1);
        // 递归构建右子树,右子树的中序遍历区间为 [rootIndex + 1, inEnd],后序遍历区间为 [postStart + leftSize, postEnd - 1]
        root.right = dfs(inorder, rootIndex + 1, inEnd, postorder, postStart + leftSize, postEnd - 1);
        // 返回构建好的当前子树的根节点
        return root;
    }
}

117. 填充每个节点的下一个右侧节点指针 II

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node next;

    public Node() {}
    
    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, Node _left, Node _right, Node _next) {
        val = _val;
        left = _left;
        right = _right;
        next = _next;
    }
};
*/

class Solution {
    public Node connect(Node root) {
        // 如果根节点为 null,则直接返回 null
        if (root == null) {
            return null;
        }

        Node head = root; // 当前层的头节点

        // 循环遍历每一层,从上至下
        while (head!= null) {
            // 创建下一层的虚拟头节点
            Node dummy = new Node(0);
            Node temp = dummy; // 当前处理的节点

            // 遍历当前层,连接下一层的节点
            for (Node cur = head; cur!= null; cur = cur.next) {
                // 如果当前节点有左子节点
                if (cur.left!= null) {
                    temp.next = cur.left;
                    temp = temp.next; // 将 temp 移动到新连接的节点上
                }
                // 如果当前节点有右子节点
                if (cur.right!= null) {
                    temp.next = cur.right;
                    temp = temp.next; // 将 temp 移动到新连接的节点上
                }
            }
            // 移动到下一层的实际头节点处
            head = dummy.next;
        }

        return root;
    }
}

114. 二叉树展开为链表

/**
 * 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 void flatten(TreeNode root) {
        List<TreeNode> result = new ArrayList<>(); // 用于存储树节点的列表
        helper(root, result); // 调用辅助方法填充节点列表

        // 遍历结果列表,并重建链表的左右指针
        for (int i = 0; i < result.size() - 1; i++) {
            TreeNode pre = result.get(i); // 当前节点
            TreeNode next = result.get(i + 1); // 下一个节点
            pre.left = null; // 将当前节点的左指针设为 null
            pre.right = next; // 将当前节点的右指针指向下一个节点
        }
    }

    // 辅助方法:进行前序遍历并收集节点
    public void helper(TreeNode root, List<TreeNode> result) {
        if (root != null) { // 检查当前节点是否为空
            result.add(root); // 将当前节点添加到结果列表中
            helper(root.left, result); // 递归处理左子树
            helper(root.right, result); // 递归处理右子树
        }
    }

}

112. 路径总和

/**
 * 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 {

    /**
     * 此方法用于判断二叉树中是否存在根节点到叶子节点的路径,使得路径上节点值的和等于给定的目标值
     *
     * @param root 二叉树的根节点
     * @param sum 目标和
     * @return 如果存在这样的路径返回 true,否则返回 false
     */
    public boolean hasPathSum(TreeNode root, int targetSum) {
        // 如果根节点为空,直接返回 false,因为不存在路径
        if (root == null) {
            return false;
        }
        // 如果当前节点是叶子节点(左右子节点都为空)
        if (root.left == null && root.right == null) {
            // 检查当前节点的值是否等于目标和
            return root.val == targetSum;
        }
        // 递归地检查左子树中是否存在满足条件的路径
        boolean left = hasPathSum(root.left, targetSum - root.val);
        // 递归地检查右子树中是否存在满足条件的路径
        boolean right = hasPathSum(root.right, targetSum - root.val);
        // 如果左子树或右子树中存在满足条件的路径,返回 true
        return left || right;
    }

}

129. 求根节点到叶节点数字之和

/**
 * 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 sumNumbers(TreeNode root) {
        // 调用深度优先搜索方法从根节点开始计算路径数字之和
        return dfs(root, 0);
    }

    private int dfs(TreeNode root, int preSum) {
        // 如果当前节点为 null,说明此分支无法形成有效路径,返回 0
        if (root == null) {
            return 0;
        }
        // 计算当前路径上的数字,即上一层传递下来的数字乘以 10 再加上当前节点的值
        int sum = preSum * 10 + root.val;
        // 如果当前节点是叶子节点,说明找到了一条完整的路径,直接返回当前路径上的数字
        if (root.left == null && root.right == null) {
            return sum;
        }
        // 如果当前节点不是叶子节点,继续递归遍历左子树和右子树,并将当前路径上的数字传递下去
        return dfs(root.left, sum) + dfs(root.right, sum);
    }
}

173. 二叉搜索树迭代器

/**
 * 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 BSTIterator {
    // 当前遍历到的节点
    private TreeNode cur;
    // 存储遍历路径上的节点的栈
    private Deque<TreeNode> stack;

    public BSTIterator(TreeNode root) {
        // 初始化时将当前节点设为根节点
        cur = root;
        // 初始化栈
        stack = new LinkedList<TreeNode>();
    }
    
    public int next() {
        // 当当前节点不为 null 时,一直将左子节点入栈,直到找到最左节点
        while (cur!= null) {
            stack.push(cur);
            cur = cur.left;
        }
        // 弹出栈顶节点,即为下一个最小的节点
        cur = stack.pop();
        int ret = cur.val;
        // 将当前节点指向弹出节点的右子节点,继续下一轮遍历
        cur = cur.right;
        return ret;
    }
    
    public boolean hasNext() {
        // 判断是否还有下一个节点,只要当前节点不为 null 或者栈不为空,就表示还有下一个节点
        return cur!= null ||!stack.isEmpty();
    }
}
/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator obj = new BSTIterator(root);
 * int param_1 = obj.next();
 * boolean param_2 = obj.hasNext();
 */

222. 完全二叉树的节点个数

/**
 * 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 {

    /**
     * 该方法用于计算给定二叉树中的节点总数
     *
     * @param root 二叉树的根节点
     * @return 二叉树的节点总数
     */
    public int countNodes(TreeNode root) {
        // 如果根节点为空,返回 0,表示没有节点
        if (root == null) {
            return 0;
        }
        // 递归计算左子树的节点数
        int leftCount = countNodes(root.left);
        // 递归计算右子树的节点数
        int rightCount = countNodes(root.right);
        // 加上当前根节点 1,返回总的节点数
        return leftCount + rightCount + 1;
    }
}

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

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

    // 存储最近公共祖先节点
    private TreeNode ans;

    private boolean dfs(TreeNode root, TreeNode p, TreeNode q) {
        // 如果当前节点为 null,则返回 false,表示未找到 p 和 q
        if (root == null) return false;

        // 递归遍历左子树,看左子树中是否有 p 和 q
        boolean lson = dfs(root.left, p, q);
        // 递归遍历右子树,看右子树中是否有 p 和 q
        boolean rson = dfs(root.right, p, q);

        // 如果左子树和右子树都有 p 和 q,或者当前节点的值等于 p 或 q 的值,并且左子树或右子树中有 p 和 q,那么当前节点就是最近公共祖先
        if ((lson && rson) || ((root.val == p.val || root.val == q.val) && (lson || rson))) {
            ans = root;
        } 

        // 返回当前子树中是否有 p 和 q,即左子树中有或者右子树中有或者当前节点等于 p 或 q
        return lson || rson || (root.val == p.val || root.val == q.val);
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 调用深度优先搜索方法来查找最近公共祖先
        this.dfs(root, p, q);
        // 返回找到的最近公共祖先节点
        return this.ans;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值