auto commit

This commit is contained in:
CyC2018 2018-12-30 14:22:17 +08:00
parent 82052b9028
commit d5c7147e4e
5 changed files with 26 additions and 27 deletions

View File

@ -702,8 +702,6 @@ HTTPs 采用混合的加密机制,使用非对称密钥加密用于传输对
进行 HTTPs 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。 进行 HTTPs 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。
通信开始时,客户端需要使用服务器的公开密钥将自己的私有密钥传输给服务器,之后再进行对称密钥加密。
<div align="center"> <img src="pics/2017-06-11-ca.png" width=""/> </div><br> <div align="center"> <img src="pics/2017-06-11-ca.png" width=""/> </div><br>
## 完整性保护 ## 完整性保护
@ -718,6 +716,7 @@ HTTPs 的报文摘要功能之所以安全,是因为它结合了加密和认
- 因为需要进行加密解密等过程,因此速度会更慢; - 因为需要进行加密解密等过程,因此速度会更慢;
- 需要支付证书授权的高额费用。 - 需要支付证书授权的高额费用。
# 七、HTTP/2.0 # 七、HTTP/2.0
## HTTP/1.x 缺陷 ## HTTP/1.x 缺陷

View File

@ -460,6 +460,7 @@ G1 把堆划分成多个大小相等的独立区域Region新生代和
**注意** 加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的类的加载过程必须按照这种顺序按部就班地**开始**,强调开始是因为这些阶段通常都是**相互交叉地混合式进行的**,通常在一个阶段执行的过程中调用另一个阶段(比如加载阶段需要验证字节码,这就需要调用验证阶段,即加载阶段还没有结束,但是验证阶段已经开始),但是两个阶段的开始时间仍然保持着固定的先后顺序。 **注意** 加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的类的加载过程必须按照这种顺序按部就班地**开始**,强调开始是因为这些阶段通常都是**相互交叉地混合式进行的**,通常在一个阶段执行的过程中调用另一个阶段(比如加载阶段需要验证字节码,这就需要调用验证阶段,即加载阶段还没有结束,但是验证阶段已经开始),但是两个阶段的开始时间仍然保持着固定的先后顺序。
## 类加载过程 ## 类加载过程
包含了加载、验证、准备、解析和初始化这 5 个阶段。 包含了加载、验证、准备、解析和初始化这 5 个阶段。

View File

@ -2315,11 +2315,8 @@ public void solveSudoku(char[][] board) {
colsUsed[j][num] = true; colsUsed[j][num] = true;
cubesUsed[cubeNum(i, j)][num] = true; cubesUsed[cubeNum(i, j)][num] = true;
} }
for (int i = 0; i < 9; i++) {
backtracking(i, 0); backtracking(i, 0);
} }
}
private boolean backtracking(int row, int col) { private boolean backtracking(int row, int col) {
while (row < 9 && board[row][col] != '.') { while (row < 9 && board[row][col] != '.') {

View File

@ -82,7 +82,7 @@ N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 的增长数量级为 O(N<sup>3</sup>)。增
### 5. 均摊分析 ### 5. 均摊分析
将所有操作的总成本除于操作总数来将成本均摊。例如对一个空栈进行 N 次连续的 push() 调用需要访问数组的元素为 N+4+8+16+...+2N=5N-4N 是向数组写入元素,其余的都是调整数组大小时进行复制需要的访问数组操作),均摊后每次操作访问数组的平均次数为常数。 将所有操作的总成本除于操作总数来将成本均摊。例如对一个空栈进行 N 次连续的 push() 调用需要访问数组的次数为 N+4+8+16+...+2N=5N-4N 是向数组写入元素的操作次数,其余的都是调整数组大小时进行复制需要的访问数组次数),均摊后访问数组的平均次数为常数。
## ThreeSum ## ThreeSum
@ -266,7 +266,7 @@ public class StopWatch {
待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。 待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。
研究排序算法的成本模型时,计的是比较和交换的次数。 研究排序算法的成本模型时,计的是比较和交换的次数。
使用辅助函数 less() 和 swap() 来进行比较和交换的操作,使得代码的可读性和可移植性更好。 使用辅助函数 less() 和 swap() 来进行比较和交换的操作,使得代码的可读性和可移植性更好。
@ -565,7 +565,7 @@ private int partition(T[] nums, int l, int h) {
快速排序是原地排序,不需要辅助数组,但是递归调用需要辅助栈。 快速排序是原地排序,不需要辅助数组,但是递归调用需要辅助栈。
快速排序最好的情况下是每次都正好将数组对半分,这样递归调用次数才是最少的。这种情况下比较次数为 C<sub>N</sub>=2C<sub>N/2</sub>+N复杂度为 O(NlogN)。 快速排序最好的情况下是每次都正好将数组对半分,这样递归调用次数才是最少的。这种情况下比较次数为 C<sub>N</sub>=2C<sub>N/2</sub>+N复杂度为 O(NlogN)。
最坏的情况下,第一次从最小的元素切分,第二次从第二小的元素切分,如此这般。因此最坏的情况下需要比较 N<sup>2</sup>/2。为了防止数组最开始就是有序的在进行快速排序时需要随机打乱数组。 最坏的情况下,第一次从最小的元素切分,第二次从第二小的元素切分,如此这般。因此最坏的情况下需要比较 N<sup>2</sup>/2。为了防止数组最开始就是有序的在进行快速排序时需要随机打乱数组。
@ -577,13 +577,13 @@ private int partition(T[] nums, int l, int h) {
#### 4.2 三数取中 #### 4.2 三数取中
最好的情况下是每次都能取数组的中位数作为切分元素,但是计算中位数的代价很高。人们发现取 3 个元素并将大小居中的元素作为切分元素的效果最好 最好的情况下是每次都能取数组的中位数作为切分元素,但是计算中位数的代价很高。一种折中方法是取 3 个元素,并将大小居中的元素作为切分元素
#### 4.3 三向切分 #### 4.3 三向切分
对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。 对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。
三向切分快速排序对于只有若干不同主键的随机数组可以在线性时间内完成排序。 三向切分快速排序对于有大量重复元素的随机数组可以在线性时间内完成排序。
```java ```java
public class ThreeWayQuickSort<T extends Comparable<T>> extends QuickSort<T> { public class ThreeWayQuickSort<T extends Comparable<T>> extends QuickSort<T> {
@ -643,7 +643,7 @@ public T select(T[] nums, int k) {
### 1. 堆 ### 1. 堆
的某个节点的值总是大于等于子节点的值,并且堆是一颗完全二叉树。 中某个节点的值总是大于等于其子节点的值,并且堆是一颗完全二叉树。
堆可以用数组来表示,这是因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。 堆可以用数组来表示,这是因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。
@ -798,7 +798,7 @@ public class HeapSort<T extends Comparable<T>> extends Sort<T> {
堆排序是一种原地排序,没有利用额外的空间。 堆排序是一种原地排序,没有利用额外的空间。
现代操作系统很少使用堆排序,因为它无法利用局部性原理进行缓存,也就是数组元素很少和相邻的元素进行比较。 现代操作系统很少使用堆排序,因为它无法利用局部性原理进行缓存,也就是数组元素很少和相邻的元素进行比较和交换
## 小结 ## 小结
@ -809,13 +809,15 @@ public class HeapSort<T extends Comparable<T>> extends Sort<T> {
| 选择排序 | × | N<sup>2</sup> | 1 | | | 选择排序 | × | N<sup>2</sup> | 1 | |
| 冒泡排序 | √ | N<sup>2</sup> | 1 | | | 冒泡排序 | √ | N<sup>2</sup> | 1 | |
| 插入排序 | √ | N \~ N<sup>2</sup> | 1 | 时间复杂度和初始顺序有关 | | 插入排序 | √ | N \~ N<sup>2</sup> | 1 | 时间复杂度和初始顺序有关 |
| 希尔排序 | × | N 的若干倍乘于递增序列的长度 | 1 | | | 希尔排序 | × | N 的若干倍乘于递增序列的长度 | 1 | 改进版插入排序 |
| 快速排序 | × | NlogN | logN | | | 快速排序 | × | NlogN | logN | |
| 三向切分快速排序 | × | N \~ NlogN | logN | 适用于有大量重复主键| | 三向切分快速排序 | × | N \~ NlogN | logN | 适用于有大量重复主键|
| 归并排序 | √ | NlogN | N | | | 归并排序 | √ | NlogN | N | |
| 堆排序 | × | NlogN | 1 | | | | 堆排序 | × | NlogN | 1 | 无法利用局部性原理|
快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 \~cNlogN这里的 c 比其它线性对数级别的排序算法都要小。使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。 快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 \~cNlogN这里的 c 比其它线性对数级别的排序算法都要小。
使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。
### 2. Java 的排序算法实现 ### 2. Java 的排序算法实现
@ -831,7 +833,7 @@ Java 主要排序方法为 java.util.Arrays.sort(),对于原始数据类型使
| :---: | :---: | | :---: | :---: |
| UF(int N) | 构造一个大小为 N 的并查集 | | UF(int N) | 构造一个大小为 N 的并查集 |
| void union(int p, int q) | 连接 p 和 q 节点 | | void union(int p, int q) | 连接 p 和 q 节点 |
| int find(int p) | 查找 p 所在的连通分量 | | int find(int p) | 查找 p 所在的连通分量编号 |
| boolean connected(int p, int q) | 判断 p 和 q 节点是否连通 | | boolean connected(int p, int q) | 判断 p 和 q 节点是否连通 |
```java ```java
@ -858,7 +860,7 @@ public abstract class UF {
## Quick Find ## Quick Find
可以快速进行 find 操作,可以快速判断两个节点是否连通。 可以快速进行 find 操作,也就是可以快速判断两个节点是否连通。
需要保证同一连通分量的所有节点的 id 值相等。 需要保证同一连通分量的所有节点的 id 值相等。
@ -937,7 +939,7 @@ public class QuickUnionUF extends UF {
这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为节点的数目。 这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为节点的数目。
<div align="center"> <img src="pics/bfbb11e2-d208-4efa-b97b-24cd40467cd8.png" width="150"/> </div><br> <div align="center"> <img src="pics/bfbb11e2-d208-4efa-b97b-24cd40467cd8.png" width="130"/> </div><br>
## 加权 Quick Union ## 加权 Quick Union
@ -945,7 +947,7 @@ public class QuickUnionUF extends UF {
理论研究证明,加权 quick-union 算法构造的树深度最多不超过 logN。 理论研究证明,加权 quick-union 算法构造的树深度最多不超过 logN。
<div align="center"> <img src="pics/a4c17d43-fa5e-4935-b74e-147e7f7e782c.png" width="200"/> </div><br> <div align="center"> <img src="pics/a4c17d43-fa5e-4935-b74e-147e7f7e782c.png" width="170"/> </div><br>
```java ```java
public class WeightedQuickUnionUF extends UF { public class WeightedQuickUnionUF extends UF {
@ -1210,8 +1212,6 @@ public class ListStack<Item> implements MyStack<Item> {
## 队列 ## 队列
First-In-First-Out
下面是队列的链表实现,需要维护 first 和 last 节点指针,分别指向队首和队尾。 下面是队列的链表实现,需要维护 first 和 last 节点指针,分别指向队首和队尾。
这里需要考虑 first 和 last 指针哪个作为链表的开头。因为出队列操作需要让队首元素的下一个元素成为队首,所以需要容易获取下一个元素,而链表的头部节点的 next 指针指向下一个元素,因此可以让 first 指针链表的开头。 这里需要考虑 first 和 last 指针哪个作为链表的开头。因为出队列操作需要让队首元素的下一个元素成为队首,所以需要容易获取下一个元素,而链表的头部节点的 next 指针指向下一个元素,因此可以让 first 指针链表的开头。
@ -2185,10 +2185,10 @@ private void resize(int cap) {
| 算法 | 插入 | 查找 | 是否有序 | | 算法 | 插入 | 查找 | 是否有序 |
| :---: | :---: | :---: | :---: | | :---: | :---: | :---: | :---: |
| 二分查找实现的有序表 | N | logN | yes | | 链表实现的无序符号表 | N | N | yes |
| 二分查找实现的有序符号表 | N | logN | yes |
| 二叉查找树 | logN | logN | yes | | 二叉查找树 | logN | logN | yes |
| 2-3 查找树 | logN | logN | yes | | 2-3 查找树 | logN | logN | yes |
| 链表实现的有序表 | N | N | no |
| 拉链法实现的散列表 | N/M | N/M | no | | 拉链法实现的散列表 | N/M | N/M | no |
| 线性探测法实现的散列表 | 1 | 1 | no | | 线性探测法实现的散列表 | 1 | 1 | no |
@ -2233,6 +2233,8 @@ public class SparseVector {
<div align="center"> <img src="pics/54f1e052-0596-4b5e-833c-e80d75bf3f9b.png" width="300"/> </div><br> <div align="center"> <img src="pics/54f1e052-0596-4b5e-833c-e80d75bf3f9b.png" width="300"/> </div><br>
有三个柱子,分别为 from、buffer、to。需要将 from 上的圆盘全部移动到 to 上,并且要保证小圆盘始终在大圆盘上。
这是一个经典的递归问题,分为三步求解: 这是一个经典的递归问题,分为三步求解:
① 将 n-1 个圆盘从 from -> buffer ① 将 n-1 个圆盘从 from -> buffer