树这种数据结构包括根节点root,左右节点,子树中又有父节点,子节点,兄弟节点,没有子节点的成为叶子节点,树分为二叉树和多叉树
List 就是特殊化的tree,Tree就是特殊化的
Graph
二分搜索树
二分搜索树(英语:Binary Search Tree),也称为 有序二叉树或排序二叉树。满足以下几个条件:
- 若它的左子树不为空,左子树上所有节点的值都小于它的根节点。
- 若它的右子树不为空,右子树上所有的节点的值都大于它的根节点。
- 它的左、右子树也都是二分搜索树。
二分搜索树的优势:不仅可以查找数据,还可以高效的插入、删除数据
注意二分搜索树不一定是完全二叉树
树的遍历
- 前序:根-左-右
- 中序:左-根-右
- 后序:左-右-根
101. 对称二叉树 (easy)
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:输入:root = [1,2,2,null,3,null,3]
输出:false提示:
树中节点数目在范围 [1, 1000] 内
-100 <= Node.val <= 100进阶:你可以运用递归和迭代两种方法解决这个问题吗?
方法1.dfs递归
- 复杂度:时间复杂度
O(n)
,每个节点遍历一次,空间复杂度O(n)
,递归栈深度,最深不超过n
js:
var isSymmetric = function(root) {
if(!root) return true
const isMirror = (l, r) => {
if(!l && !r) return true; //两个空节点也为镜像
if(
l && r && l.val === r.val && //左节点和右节点相同,左子树和右子树也对称则返回true
isMirror(l.left, r.right) &&
isMirror(l.right, r.left)
) {
return true;
}
return false;
}
return isMirror(root.left, root.right)
};
方法2.bfs
- 复杂度:时间复杂度
O(n)
,每个节点遍历一次,空间复杂度O(n)
,队列的空间
js:
function isSymmetric(root) {
const isMirror = (l, r) => {
const queue = [l, r];
while (queue.length) {
const u = queue.shift();
const v = queue.shift();
if (!u && !v) continue; //两个空节点也为镜像
//左右节点只有一个节点为空,或者值不相同返回false
if (!u || !v || u.val !== v.val) return false;
queue.push(u.left, v.right); //加入左节点的左子树,右节点的右子树
queue.push(v.left, u.right); //加入右节点的左子树,左节点的右子树
}
return true;
};
return isMirror(root.left, root.right);
}
100. 相同的树(easy)
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入:p = [1,2,3], q = [1,2,3]
输出:true
示例 2:输入:p = [1,2], q = [1,null,2]
输出:false
示例 3:输入:p = [1,2,1], q = [1,1,2]
输出:false提示:
两棵树上的节点数目都在范围 [0, 100] 内
-104 <= Node.val <= 104
方法1.dfs递归
- 思路:递归比较左右子树
- 复杂度:时间复杂度
O(n)
,n是节点较少的树中的节点个数,递归有一个节点为null,另一个不为null就停止递归,空间复杂度O(n)
,递归深度不会超过节点个数
js:
var isSameTree = function(p, q) {
if(p == null && q == null) //都是null表示相同
return true;
if(p == null || q == null) //只有一个是null表示不同
return false;
if(p.val != q.val) //节点的值不同
return false;
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);//递归左右子树
};
方法2bfs:
- 复杂度:时间复杂度
O(n)
,n是节点较少的树中的节点个数,空间复杂度O(n)
,队列的空间不会超过节点较少的树中的节点个数
js:
var isSameTree = function(p, q) {
let pQ = [p], qQ = [q], res = true
while (pQ.length) {
pNode = pQ.shift()
qNode = qQ.shift()
if (pNode === null && qNode === null) {
res = true
} else if (pNode === null || qNode === null) {
res = false
break
} else {
if (pNode.val !== qNode.val) {
res = false
break
} else {
pQ.push(pNode.left)
pQ.push(pNode.right)
qQ.push(qNode.left)
qQ.push(qNode.right)
}
}
}
return res
};
297. 二叉树的序列化与反序列化 (hard)
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例 1:
输入:root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]
示例 2:输入:root = []
输出:[]
示例 3:输入:root = [1]
输出:[1]
示例 4:输入:root = [1,2]
输出:[1,2]提示:
树中结点数在范围 [0, 104] 内
-1000 <= Node.val <= 1000
方法1.递归dfs
- 思路:深度优先遍历,按根,左,右 返回字符串,方便反序列化的时候从根节点开始构建,递归左右子树,直到遇见了null节点。
- 复杂度:时间复杂度
O(n)
,每个节点访问一次,n是树的节点个数。空间复杂度O(n)
,最坏情况下递归深度是n
js:
const serialize = (