二叉树(BS)
- 第i层最多有 2 i 2^i 2i 个结点 ( i = 0 , 1 , 2 ⋯ i = 0, 1 ,2 \cdots i=0,1,2⋯)
- 高度为h的二叉树至多有 2 ( h + 1 ) − 1 2^{(h + 1)} - 1 2(h+1)−1 个结点 ( h = 0 , 1 , 2 ⋯ h = 0, 1 ,2 \cdots h=0,1,2⋯)
- n 0 n_0 n0 = n 2 n_2 n2 + 1
- 具有n个结点的完全二叉树的高度为 l o g n logn logn 向下取整
- 对于完全二叉树,其结点编号
i
i
i(1 <=
i
i
i <= n)
- i = 1 i = 1 i=1,根结点,无双亲
- i > 1 i > 1 i>1 && 2 i < = n 2i <= n 2i<=n,左孩子 2 i 2i 2i
- i > 1 i > 1 i>1 && 2 i + 1 < = n 2i + 1 <= n 2i+1<=n,右孩子 2 i + 1 2i + 1 2i+1
二叉查找树(BST)
一棵空树,或者是具有下列性质的 二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。
(5)它的中序遍历是升序的
二叉平衡树(AVL)
AVL树本质上还是 一棵二叉搜索树,它的特点是
- 本身首先是一棵二叉搜索树。
- 带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树)
- 删除结点度为0、1、2的结点
红黑树(Red Black Tree)
- 红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
- 它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目
- LL旋转、RR旋转、LR旋转、RL旋转
B树(B Tree)
#TODO
字典树(Trie)
- 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。
- 典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
- 它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
它有3个基本性质:
- 根节点不包含字符,除根节点外每一个节点都只包含一个字符
- 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串
- 每个节点的所有子节点包含的字符都不相同
线段树(Segment Tree)
- 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点
- 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度
- 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩
题目实战
144 二叉树的前序遍历
- https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
中后序遍历如同、递归写法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null) return list;
list.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return list;
}
}
非递归写法
手动维护一个栈
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode current = root;
while (current != null || !stack.isEmpty()) {
while (current != null) {
res.add(current.val);
stack.push(current);
current = current.left;
}
current = stack.pop();
current = current.right;
}
return res;
}
}
102 二叉树的层次遍历
- https:/leetcode-cn.com/problems/binary-tree-level-order-traversal/
手动维护一个队列
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> lists = new ArrayList<List<Integer>>();
if (root == null) return lists;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int level = 0;
while ( !queue.isEmpty() ) {
lists.add(new ArrayList<Integer>());
int len = queue.size();
for(int i = 0; i < len; ++i) {
TreeNode node = queue.remove();
lists.get(level).add(node.val);
if (node.left != null) queue.add(node.left);
if (node.right != null) queue.add(node.right);
}
level++;
}
return lists;
}
}
104 二叉树的最大深度
- https:/leetcode-cn.com/problems/maximum-depth-of-binary-tree/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int level;
public int maxDepth(TreeNode root) {
if(root == null) return 0;
int maxLeft = maxDepth(root.left);
int maxRight = maxDepth(root.right);
return Math.max(maxLeft, maxRight) + 1;
}
}
114 二叉树展开为链表
- https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/
/**
* 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) {
if(root == null){
return ;
}
//将根节点的左子树变成链表
flatten(root.left);
//将根节点的右子树变成链表
flatten(root.right);
TreeNode temp = root.right;
//把树的右边换成左边的链表
root.right = root.left;
//记得要将左边置空
root.left = null;
//找到树的最右边的节点
while(root.right != null) root = root.right;
//把右边的链表接到刚才树的最右边的节点
root.right = temp;
}
}
从中序与后遍历列构造二叉树
- https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
HashMap<Integer,Integer> memo = new HashMap<>();
int[] post;
public TreeNode buildTree(int[] inorder, int[] postorder) {
for(int i = 0;i < inorder.length; i++) memo.put(inorder[i], i);
post = postorder;
TreeNode root = buildTree(0, inorder.length - 1, 0, post.length - 1);
return root;
}
public TreeNode buildTree(int is, int ie, int ps, int pe) {
if(ie < is || pe < ps) return null;
int root = post[pe];
int ri = memo.get(root);
TreeNode node = new TreeNode(root);
node.left = buildTree(is, ri - 1, ps, ps + ri - is - 1);
node.right = buildTree(ri + 1, ie, ps + ri - is, pe - 1);
return node;
}
}
从前序与中遍历列构造二叉树
(同上)
根据前序和后遍历构造二叉树
(同上上)
对称二叉树
- https://leetcode-cn.com/problems/symmetric-tree/
将其转化为回文串问题
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
static StringBuilder sb = new StringBuilder();
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
preorder(root);
return isPalindrome(sb);
}
public static void preorder(TreeNode root){
if(root == null) return;
preorder(root.left);
sb.append("" + root.val);
preorder(root.right);
}
public static boolean isPalindrome(StringBuilder sb){
String s1 = sb.toString();
String s2 = sb.reverse().toString();
return s1.equals(s2);
}
}
使用队列(类似BFS的改造)
public boolean isSymmetric(TreeNode root) {
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
q.add(root);
while (!q.isEmpty()) {
TreeNode t1 = q.poll();
TreeNode t2 = q.poll();
if (t1 == null && t2 == null) continue;
if (t1 == null || t2 == null) return false;
if (t1.val != t2.val) return false;
q.add(t1.left);
q.add(t2.right);
q.add(t1.right);
q.add(t2.left);
}
return true;
}
使用递归
public boolean isSymmetric(TreeNode root) {
return isMirror(root, root);
}
public boolean isMirror(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;
return (t1.val == t2.val)
&& isMirror(t1.right, t2.left)
&& isMirror(t1.left, t2.right);
}
450 删除二叉搜索树中的节点
- https://leetcode-cn.com/problems/delete-node-in-a-bst/
700 二叉搜索树中的搜索
- https://leetcode-cn.com/problems/search-in-a-binary-search-tree/
701 二叉搜索树中的插入操作
- https://leetcode-cn.com/problems/insert-into-a-binary-search-tree/
1361 验证二叉搜索树
- https://leetcode-cn.com/problems/validate-binary-search-tree
530 二叉搜索树的最小绝对差
https://leetcode-cn.com/problems/minimum-absolute-difference-in-bst
783 二叉搜索树结点最小距离
- https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes
108 将有序数组转换为二叉搜索树
- https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree
二叉搜索树的范围和
- https://leetcode-cn.com/problems/range-sum-of-bst
二叉搜索树的最近公共祖先
- https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree
230 二叉搜索树中第 K小的元素
- https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst
173 二叉搜索树迭代器
- https://leetcode-cn.com/problems/binary-search-tree-iterator
99 恢复二叉搜索树
- https://leetcode-cn.com/problems/recover-binary-search-tree
110 平衡二叉树
- https://leetcode-cn.com/problems/balanced-binary-tree/