mindmap
二叉树
二叉树遍历方式
前序
后序
中序
层序
二叉树属性
对称二叉树
最大深度
最小深度
完全二叉树的节点个数
平衡二叉树
二叉树的所有路径
左叶子之和
找树左下角的值
路径总和
二叉树的修改和构造
翻转二叉树
从中序与后序遍历构造二叉树
最大二叉树
合并二叉树
二叉搜索树的属性
二叉搜索树中的搜索
验证二叉搜索树
二叉搜索树的最小绝对差
二叉搜索树中的众数
把二叉搜索树转换为累加树
二叉树公共祖先问题
二叉树的最近公共祖先
二叉搜索树的最近公共祖先
二叉搜索树的修改与构造
二叉搜索树中的插入操作
删除二叉搜索树中的节点
修剪二叉搜索树
将有序数组转换为二叉搜索树
二叉树种类
1.满二叉树
这棵二叉树为满二叉树,也可以说深度为k,有2^k-1个节点的二叉树。
2.完全二叉树
在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。
3.二叉搜索树
二叉搜索树是一个有序树。
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉排序树
这两棵树都是二叉搜索树
4.平衡二叉搜索树
又被称为AVL树,他是一个空树或者它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
二叉树的存储方式
- 链式存储(指针,常用)
- 顺序存储(数组)
二叉树的遍历方式
- 深度优先
- 前序遍历(中左右)
- 中序遍历(左中右)
- 后序遍历(左右中)
- 广度优先
- 层序遍历
二叉树的遍历
递归遍历
//1.前序遍历
public void preorder(TreeNode root, List<Integer> result) {
if (root == null) {
return;
}
result.add(root.val);
preorder(root.left, result);
preorder(root.right, result);
}
//2.中序遍历
void inorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
inorder(root.left, list);
list.add(root.val); // 注意这一句
inorder(root.right, list);
}
//3.后序遍历
void postorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
postorder(root.left, list);
postorder(root.right, list);
list.add(root.val); // 注意这一句
}
层序遍历
public List<List<Integer>> levelOder(TreeNode root){
List<List<Integer>> res = new ArrayList<>();
if(root==null){
return res;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size = queue.size();
List<Integer> list = new ArrayList<>();
for(int i=0;i<size;i++){
TreeNode cur = queue.poll();
list.add(cur.val);
if(cur.left!=null){
queue.offer(cur.left);
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
res.add(list);
}
return res;
}
二叉树的属性
二叉树属性问题1:104.二叉树的最大深度
【问题】
给定一个二叉树 `root` ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
【解答】
//方法一:深度优先递归
public int maxDepth(TreeNode root) {
if(root==null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
//方法二:层序遍历
二叉树属性问题2:111.二叉树的最小深度
【解答】
//方法1:深度优先
public int minDepth(TreeNode root) {
if(null==root){
return 0;
}
if(null==root.left && null==root.right){
return 1;
}
//分别计算其左右子树的最小叶子节点深度
int min = Integer.MAX_VALUE;
if(null!=root.left){
min = Math.min(min,minDepth(root.left));
}
if(null!=root.right){
min = Math.min(min,minDepth(root.right));
}
return min+1;
}
//方法二:层序遍历(广度优先)
在每一层判断是否出现节点的左右子节点为空即可,更简单理解
二叉树属性问题3: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(null==left && null==right){
return true;
}
if(null==left || null==right){
return false;
}
if(left.val!=right.val){
return false;
}
return isSymmetric(left.left,right.right)
&& isSymmetric(left.right,right.left);
}
二叉树属性问题4:222.完全二叉树的节点个数
给出一个完全二叉树,求出该树的节点个数。
//方法一:深度优先,通用的计算节点个数方法
public int countNodes(TreeNode root) {
if(null==root){
return 0;
}
return countNodes(root.left)+countNodes(root.right)+1;
}
//方法二:广度优先,遍历所有的节点
//方法三:针对满二叉树的处理
//如果是满二叉树,那么节点数=2^深度-1,如果深度是3,满二叉树的节点数=7
//满二叉树是完全二叉树,但是完全二叉树可能不是满二叉树
public int countNodes(TreeNode root) {
if(root==null){
return 0;
}
int leftDepth =0;
TreeNode left = root;
while(left!=null){
leftDepth++;
left = left.left;
}
int rightDepth =0;
TreeNode right = root;
while(left!=null){
rightDepth++;
right = right.right;
}
if(leftDepth==rightDepth){
return 2>>leftDepth-1;
}
return countNodes(root.left)+countNodes(root.right)+1;
}
二叉树属性问题5:110.平衡二叉树
【问题】
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。
【解答】
public boolean isBalanced(TreeNode root) {
if(root==null){
return true;
}
if(Math.abs(depth(root.left)-depth(root.right))>1){
return false;
}
return isBalanced(root.left) && isBalanced(root.right);
}
public int depth(TreeNode t1) {
if(null==t1){
return 0;
}
return Math.max(depth(t1.left),depth(t1.right))+1;
}
二叉树属性问题6:257.二叉树的所有路径
【问题】
给你一个二叉树的根节点 `root` ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
【答案】
List<String> res = new ArrayList<>();
public List<String> binaryTreePaths(TreeNode root) {
dfs(null,root);
return res;
}
//为空:直接结束
//1.将节点数据存入字符串
//2.判断当前节点是否是路径终点,是则加入结果集
//3.若不是终点,则让其左右非空的子节点继续走递归逻辑
public void dfs(String str,TreeNode root){
if(null==root){
return;
}
String nextStr = null;
if(null==str){
nextStr = new String(String.valueOf(root.val));
}else{
nextStr = new String(str+"->"+root.val);
}
//如果当前的节点的左右节点皆为空,那么可以将字符串存入结果
if(null==root.left && null==root.right){
res.add(nextStr);
}
if(null!=root.left){
dfs(nextStr,root.left);
}
if(null!=root.right){
dfs(nextStr,root.right);
}
}
二叉树属性问题7:404.左叶子之和
【问题】
给定二叉树的根节点 `root` ,返回所有左叶子之和。
【解答】
int res = 0;
public int sumOfLeftLeaves(TreeNode root) {
if(null==root){
return 0;
}
if(null!=root.left
&& root.left.left==null
&& root.left.right==null){
res +=root.left.val;
}
sumOfLeftLeaves(root.left);
sumOfLeftLeaves(root.right);
return res;
}