二叉树
树的概念及基本术语见树与二叉树的基础知识
定义:一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。
特点:每个结点至多只有两棵子树(二叉树中不存在度大于2的结点)
性质:二叉树的五大性质及证明
五种形态:
Leetcode 真题
二叉树遍历
二叉树的中序遍历
解题思路:先遍历左子树,然后访问根结点,最后遍历右子树
public static List<Integer> values;
public List<Integer> inorderTraversal(TreeNode root) {
values = new ArrayList<>();
inOrder(root);
return values;
}
private void inOrder(TreeNode root) {
if (root != null) {
inOrder(root.left);
values.add(root.val);
inOrder(root.right);
}
}
二叉树的前序遍历
解题思路:先访问根结点,然后遍历左子树,最后遍历右子树
List<Integer> values;
public List<Integer> preorderTraversal(TreeNode root) {
values = new ArrayList<>();
preorder(root);
return values;
}
private void preorder(TreeNode root){
if(root != null){
values.add(root.val);
preorder(root.left);
preorder(root.right);
}
}
二叉树的后序遍历
解题思路:先遍历左子树,然后遍历右子树,最后访问根结点
List<Integer> values;
public List<Integer> postorderTraversal(TreeNode root) {
values = new ArrayList<>();
postorder(root);
return values;
}
private void postorder(TreeNode root){
if(root != null){
postorder(root.left);
postorder(root.right);
values.add(root.val);
}
}
二叉树的层序遍历
解题思路:自上而下,自左至右逐层访问树的结点的过程就是层序遍历
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> values = new ArrayList<>();
if(root == null){
return values;
}
queue.add(root);
while(!queue.isEmpty()){
int size = queue.size();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode node = queue.remove();
level.add(node.val);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
values.add(level);
}
return values;
}
二叉树递归
二叉树的最大深度
解题思路:分解为子问题再进行递归,节点的最大深度 = 左子树与右子树的最大深度 + 1
public int maxDepth(TreeNode root) {
return root == null ? 0 : 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}
路径总和
解题思路:
问题分解为子问题:假定从根节点到当前节点的值之和为 val,查找是否存在从当前节点的子节点到叶子的路径,满足其路径和为 sum - val
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
return sum == root.val;
}
return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
路径总和 II
解题思路:
同[路径总和],将问题分解为子问题:假定从根节点到当前节点的值之和为 val,查找是否存在从当前节点的子节点到叶子的路径,满足其路径和为 sum - val
区别为需记录结果集
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
LinkedList<Integer> path = new LinkedList<>();
dfs(root, targetSum, path);
return res;
}
public void dfs(TreeNode root, int targetSum, LinkedList<Integer> path) {
if (root == null) {
return;
}
targetSum -= root.val;
path.add(root.val);
if (targetSum == 0 && root.left == null && root.right == null) {
res.add(new LinkedList(path));
}
dfs(root.left, targetSum, path);
dfs(root.right, targetSum, path);
path.removeLast();
}
参考资料:
- 树、二叉树及二叉查找树
- 树与二叉树的基础知识