Compare commits

...

4 Commits

Author SHA1 Message Date
kn5886348135 55a85cd5ad 动态规划 暴力递归
3 years ago
kn5886348135 73a978cb60 并查集
3 years ago
kn5886348135 f3fd2ccad0
3 years ago
kn5886348135 2bbb30be75 并查集、二叉树和贪心算法
3 years ago

@ -0,0 +1,43 @@
## <center>并查集</center>
&emsp;&emsp;在计算机科学中并查集英文Disjoint-set data structure直译为不交集数据结构是一种数据结构用于处理一些不交集Disjoint sets一系列没有重复元素的集合的合并及查询问题。
&emsp;&emsp;解决两大块区域的合并问题,常用在图等领域中。
<br />
### 并查集的模型
* 有若干个样本a、b、c、d…类型假设是V
* 在并查集中一开始认为每个样本都在单独的集合里
* 用户可以在任何时候调用如下两个方法:
boolean isSameSet(V x, V y) : 查询样本x和样本y是否属于一个集合
void union(V x, V y) : 把x和y各自所在集合的所有样本合并成一个集合
* isSameSet和union方法的代价越低越好
### 合并
&emsp;&emsp;合并操作是将两个并查集指向同一个代表节点而不是将两个集合放到一个新的集合中。可以使用map或者数组实现合并操作。数组实现的合并操作在常数项时间复杂度更有优势。小集合挂在大集合的下面可以减少路径压缩操作。
<br />
### 查询
&emsp;&emsp;从下往上递归查找代表节点并处理路径压缩。可以借助Stack或者数组处理路径压缩。
<br />
### 并查集的特点
* 每个节点都有一条往上指的指针
* 节点a往上找到的头节点叫做a所在集合的代表节点
* 查询x和y是否属于同一个集合就是看看找到的代表节点是不是一个
* 把x和y各自所在集合的所有点合并成一个集合只需要小集合的代表点挂在大集合的代表点的下方
* 如果方法调用很频繁那么单次调用的时间复杂度为O(1)
LeetCode547 Friend Circles
使用并查集合并,最后返回子集的个数
LeetCode200 Number of Islands
给定一个二维数组matrix里面的值不是1就是0上、下、左、右相邻的1认为是一片岛返回matrix中岛的数量。
合并、查询,暴力循环(上下左右递归感染)、使用map实现并查集、使用数组实现并查集
LeetCode305 Number of Islands II
岛问题扩展
如果matrix极大设计一种可行的并行计算方案

@ -0,0 +1,75 @@
## <center></center>
### 1、图的概念
* 由点的集合和边的集合构成
* 虽然存在有向图和无向图的概念,但实际上都可以用有向图来表达
* 边上可能带有权值
&emsp;&emsp;图的表示方法邻接表法、邻接矩阵法等。题目会以各种方式给出图的表达方式可以将它转化为一种熟悉的表达方式方便操作。可以将图表示为节点和边的集合参考下面代码Graph。
```Java
public class Graph {
public Map<Integer, Node> nodes;
public Set<Edge> edges;
public Graph() {
this.nodes = new HashMap<>();
this.edges = new HashSet<>();
}
}
public class Node {
// 节点值
public int value;
// 入度
public int in;
// 出度
public int out;
// 相邻节点
public List<Node> nexts;
// 节点的边
public List<Edge> edges;
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
public class Edge {
// 边的权重
public int weight;
// 边的起始节点
public Node from;
// 边的结束节点
public Node to;
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
```
### 宽度优先遍历
* 利用队列实现
* 从源节点开始依次按照宽度进队列,然后弹出
* 每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
* 直到队列变空
### 深度优先遍历
* 利用栈实现
* 从源节点开始把节点按照深度放入栈,然后弹出
* 每弹出一个点,把该节点下一个没有进过栈的邻接点放入栈
* 直到栈变空
### 拓扑排序
&emsp;&emsp;拓扑排序是不唯一的

@ -0,0 +1,41 @@
## <center>动态规划</center>
&emsp;&emsp;暴力递归就是尝试,暴力递归是动态规划的基础,暴力递归加上合理的剪枝和缓存就是动态规划。
<br />
### 暴力递归的步骤
* 把问题转化为规模缩小了的同类问题的子问题
* 有明确的不需要继续进行递归的条件(base case递归终止条件)
* 有当得到了子问题的结果之后的决策过程
* 不记录每一个子问题的解
### 暴力递归的几个常见问题
#### 1、汉诺塔问题
&emsp;&emsp;打印n层汉诺塔从最左边移动到最右边的全部过程每次只能移动一个圆盘不能出现大盘叠在小盘上面的情况。可以分为3个步骤。
* 将1-> n-1 移动到中间
* 将n移动到右边
* 将1-> n-1移动到右边
#### 2、打印一个字符串的全部子序列
&emsp;&emsp;依次考察每一个字符是否被选中,递归逻辑可以画成整颗二叉树。每次递归前移除当前字符,递归完以后恢复当前字符。
#### 3、打印一个字符串的全部子序列要求不要出现重复字面值的子序列
&emsp;&emsp;同上加上set去重
#### 4、打印一个字符串的全部排列
&emsp;&emsp;使用index和index后面的字符交换位置index递增达到递归目的index=str.length为递归终止条件。
#### 5、打印一个字符串的全部排列要求不要出现重复的排列
&emsp;&emsp;加上visited数组去重避免重复的字符进行交换。
#### 6、反转栈不能使用额外集合只能使用递归函数
&emsp;&emsp;两个递归函数reverse使用f函数拿到栈底元素然后递归将栈底元素压栈。利用局部变量保存栈底元素系统函数调用栈保证所有元素逆序。f函数拿到栈底元素并保证其他元素顺序不变。

@ -27,10 +27,12 @@
#### 平衡二叉树 LeetCode110
判断二叉树是否是平衡二叉树
左子树的高度和右子树的高度相差不超过1则称为平衡二叉树。
#### 二叉搜索树 LeetCode98
#### 搜索二叉树 LeetCode98
判断二叉树是否是搜索二叉树
递归解决
#### 路径总和 LeetCode112
@ -44,5 +46,5 @@ X是一棵二叉树的某一个节点A是二叉树先序遍历X的左边部
X的所有祖先节点、X自己、X的子节点、X或者X的父节点作为左树的右兄节点、X或者X的父节点作为右树的左兄节点
判断二叉树是否是平衡二叉树
判断二叉树是否是搜索二叉树
给定一颗二叉树的头结点,任何两个节点之间都存在距离,返回整颗二叉树的最大距离
二叉树node的a、b两个节点的最低公共祖先可以使用递归套路也可以使用set或者map结合后序遍历实现

@ -0,0 +1,10 @@
贪心算法
a.b<<b.ab.c<<c.b a.c<<c.a
贪心算法不需要证明,使用对数器证明
分割金条60长度分成10、20、30
每次切割最大长度的反例97、98 和 100、99
反例的证明就是哈夫曼编码
将所有分割后的长度放入小根堆,每次获取两个长度相加然后放回小根堆,重复
Loading…
Cancel
Save