由上述的定义可以看出,二叉树中的节点至多包含两棵子树,分别称为左子树和右子树,而左子树和右子树又分别至多包含两棵子树。由上述的定义,二叉树的定义是一种递归的定义。
二叉树种类
满二叉树
对于一棵二叉树,如果每一个非叶子节点都存在左右子树,并且二叉树中所有的叶子节点都在同一层中,这样的二叉树称为满二叉树。
完全二叉树
对于一棵具有n个节点的二叉树按照层次编号,同时,左右子树按照先左后右编号,如果编号为i的节点与同样深度的满二叉树中编号为i的节点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树。
二叉排序树:
又称二叉查找树(Binary Search Tree),亦称二叉搜索树。二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
-
若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
-
若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
-
左、右子树也分别为二叉排序树;
-
没有键值相等的节点
二分查找的时间复杂度是O(log(n)),最坏情况下的时间复杂度是O(n)(相当于顺序查找)
平衡二叉树:
又称 AVL 树。平衡二叉树是二叉搜索树的进化版,所谓平衡二叉树指的是,左右两个子树的高度差的绝对值不超过 1。
红黑树:
红黑树是每个节点都带颜色的树,节点颜色或是红色或是黑色,红黑树是一种查找树。红黑树有一个重要的性质,从根节点到叶子节点的最长的路径不多于最短的路径的长度的两倍。对于红黑树,插入,删除,查找的复杂度都是O(log N)。
哈夫曼树:
给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。
遍历方式
二叉树主要有四种遍历方式
-
先序(先根)遍历:即先访问根节点,再访问左孩子和右孩子
-
中序遍历:先访问做孩子,再访问根节点和右孩子
-
后序遍历:先访问左孩子,再访问右孩子,再访问根节点
-
层次遍历:按照所在层数,从下往上遍历
前提:这里先给出测试中的二叉树结构,如下图所示
该二叉树对应的几种遍历方式的结果顺序:
-
先序遍历:10->6->4->8->14->12->16
-
中序遍历:4->6->8->10->12->14->16
-
后序遍历:4->8->6->12->16->14->10
-
层次遍历:10->6->14->4->8->12->16
递归
==
递归的基本思想就是把规模大的问题转化为规模小的相似的子问题来解决。
特别地,在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况,这也正是递归的定义所在。格外重要的是,这个解决问题的函数必须有明确的结束条件,否则就会导致无限递归的情况
而在树当中,一棵树要么是空树,要么有两个指针,每个指针指向一棵树。树是一种递归结构,很多树的问题可以使用递归来处理。
1. 树的高度
1.0 求二叉树的最大层数(最大深度)
104. Maximum Depth of Binary Tree (Easy)
Leetcode / 力扣
这道题目的解法其实很简单
-
如果二叉树为空,二叉树的深度为0
-
如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
1public int maxDepth(TreeNode root) {
2 if (root == null) return 0;
3 return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
4}
1.1 二叉树的最小深度
LeetCode:Minimum Depth of Binary Tree
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
解题思路
-
对于一个节点,如果左子树或者右子树为空,那么最小深度为 left + right + 1
-
如果左子树和右子树都不为空,那么最小深度为 Math.min(left,right) + 1
1class Solution {
2 public int minDepth(TreeNode root) {
3 if(root == null)
4 return 0;
5 int left = minDepth(root.left);
6 int right = minDepth(root.right);
7 return (left == 0 || right == 0) ? left + right + 1 : Math.min(left, right) + 1;
8 }
9}
2. 平衡树
110. Balanced Binary Tree (Easy)
1 3
2 / \
3 9 20
4 / \
5 15 7
思路
平衡树左右子树高度差都小于等于 1
1private boolean result = true;
2
3public boolean isBalanced(TreeNode root) {
4 maxDepth(root);
5 return result;
6}
7
8public int maxDepth(TreeNode root) {
9 if (root == null) return 0;
10 int l = maxDepth(root.left);
11 int r = maxDepth(root.right);
12 if (Math.abs(l - r) > 1) result = false;
13 return 1 + Math.max(l, r);
14}
3. 两节点的最长路径
543. Diameter of Binary Tree (Easy)
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
解题思路:
-
因为最长直径不一定过根节点,所以需要分别以每一个节点为中心计算最长路径。
-
用一个全局变量max来维护最长路径(左子树的深度+右子树的深度)。
-
为了计算每个子树的深度,使用深度优先遍历计算树中每一个节点的深度(max(左子树深度,右子树深度))
1Input:
2
3 1
4 / \
5 2 3
6 / \
7 4 5
8
9Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].
1private int max = 0;
2
3public int diameterOfBinaryTree(TreeNode root) {
4 depth(root);
5 return max;
6}
7
8private int depth(TreeNode root) {
9 if (root == null) return 0;
10 int leftDepth = depth(root.left);
11 int rightDepth = depth(root.right);
12 max = Math.max(max, leftDepth + rightDepth);
13 return Math.max(leftDepth, rightDepth) + 1;
14}
4. 翻转树
226. Invert Binary Tree (Easy)
翻转一棵二叉树
思路与算法
-
这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子结点先开始翻转。
-
如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。
1public TreeNode invertTree(TreeNode root) {
2 if (root == null) return null;
3 TreeNode left = root.left; // 后面的操作会改变 left 指针,因此先保存下来
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
面试复习路线,梳理知识,提升储备
自己的知识准备得怎么样,这直接决定了你能否顺利通过一面和二面,所以在面试前来一个知识梳理,看需不需要提升自己的知识储备是很有必要的。
关于知识梳理,这里再分享一下我面试这段时间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)
- 架构师筑基必备技能
- Android高级UI与FrameWork源码
- 360°全方面性能调优
- 解读开源框架设计思想
- NDK模块开发
- 微信小程序
- Hybrid 开发与Flutter
知识梳理完之后,就需要进行查漏补缺,所以针对这些知识点,我手头上也准备了不少的电子书和笔记,这些笔记将各个知识点进行了完美的总结:
《960全网最全Android开发笔记》
《379页Android开发面试宝典》
历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
711930688490)]
《379页Android开发面试宝典》
历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
[外链图片转存中…(img-aJYUYF2M-1711930688490)]
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。