diff --git a/notes/HTTP.md b/notes/HTTP.md
index 82c4a36a..7238542e 100644
--- a/notes/HTTP.md
+++ b/notes/HTTP.md
@@ -803,7 +803,7 @@ DELETE /idX/delete HTTP/1.1 -> Returns 404
2. HTTP/1.1 支持管线化处理
3. HTTP/1.1 支持虚拟主机
4. HTTP/1.1 新增状态码 100
-5. HTTP/1.1 只是分块传输编码
+5. HTTP/1.1 支持分块传输编码
6. HTTP/1.1 新增缓存处理指令 max-age
具体内容见上文
@@ -828,7 +828,7 @@ HTTP/1.1 的解析是基于文本的,而 HTTP/2.0 采用二进制格式。
# 参考资料
-- 上野宣. 图解 HTTP[M]. Ren min you dian chu ban she, 2014.
+- 上野宣. 图解 HTTP[M]. 人民邮电出版社, 2014.
- [MDN : HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)
- [Are http:// and www really necessary?](https://www.webdancers.com/are-http-and-www-necesary/)
- [HTTP (HyperText Transfer Protocol)](https://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html)
diff --git a/notes/JDK 中的设计模式.md b/notes/JDK 中的设计模式.md
index 8e2161cc..92f53cb3 100644
--- a/notes/JDK 中的设计模式.md
+++ b/notes/JDK 中的设计模式.md
@@ -44,11 +44,11 @@ java.awt.Desktop#getDesktop()
## 2. 简单工厂模式
-在不对用户暴露对象内部逻辑的前提下创建对象;使用通用的接口来创建对象;
+在不对用户暴露对象内部逻辑的前提下创建对象。
## 3. 工厂方法模式
-定义创建对象的接口,但是让子类来决定应该使用哪个类来创建;使用通用的接口来创建对象;
+定义创建对象的接口,但是让子类来决定应该使用哪个类来创建。
```java
java.lang.Proxy#newProxyInstance()
@@ -120,7 +120,7 @@ javax.swing.Action
## 3. 解释器模式
为语言创建解释器,通常由语言的语法和语法分析来定义。
-
+
```java
java.util.Pattern
java.text.Normalizer
@@ -229,7 +229,7 @@ JDBC
## 3. 组合模式
-将对象组合成树形结构来表示整理-部分层次关系,允许用户以相同的方式处理单独对象和组合对象。
+将对象组合成树形结构来表示整体-部分层次关系,允许用户以相同的方式处理单独对象和组合对象。
```java
javax.swing.JComponent#add(Component)
diff --git a/notes/Java 基础.md b/notes/Java 基础.md
index 50a18405..aa33ce32 100644
--- a/notes/Java 基础.md
+++ b/notes/Java 基础.md
@@ -12,7 +12,7 @@
* [访问权限](#访问权限)
* [抽象类与接口](#抽象类与接口)
* [super](#super)
- * [重载与重写](#重载与重写)
+ * [覆盖与重载](#覆盖与重载)
* [五、String](#五string)
* [String, StringBuffer and StringBuilder](#string,-stringbuffer-and-stringbuilder)
* [String 不可变的原因](#string-不可变的原因)
@@ -55,7 +55,7 @@ y.a = 1;
声明方法不能被子类覆盖。
-private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是覆盖基类方法,而是重载了。
+private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是覆盖基类方法,而是在子类中定义了一个新的方法。
**3. 类**
@@ -255,9 +255,9 @@ public class EqualExample {
## hashCode()
-hasCode() 返回散列值,而 equals() 是用来判断两个实例是否相等。相等的两个实例散列值一定要相同,但是散列值相同的两个实例不一定相等。
+hasCode() 返回散列值,而 equals() 是用来判断两个实例是否等价。等价的两个实例散列值一定要相同,但是散列值相同的两个实例不一定等价。
-在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证相等的两个实例散列值也相等。
+在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证相等的两个实例散列值也等价。
下面的代码中,新建了两个等价的实例,并将它们添加到 HashSet 中。我们希望将这两个实例当成一样的,只在集合中添加一个实例,但是因为 EqualExample 没有实现 hasCode() 方法,因此这两个实例的散列值是不同的,最终导致集合添加了两个等价的实例。
@@ -313,7 +313,7 @@ ToStringExample@4554617c
**1. cloneable**
-clone() 是 Object 的受保护方法,这意味着,如果一个类不显式去重载 clone() 就没有这个方法。
+clone() 是 Object 的受保护方法,这意味着,如果一个类不显式去覆盖 clone() 就没有这个方法。
```java
public class CloneExample {
@@ -327,7 +327,7 @@ CloneExample e1 = new CloneExample();
CloneExample e2 = e1.clone(); // 'clone()' has protected access in 'java.lang.Object'
```
-接下来重载 Object 的 clone() 得到以下实现:
+接下来覆盖 Object 的 clone() 得到以下实现:
```java
public class CloneExample {
@@ -595,7 +595,7 @@ ac2.func1();
从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类。
-接口也可以包含域,并且这些域隐式都是 static 和 final 的。
+接口也可以包含字段,并且这些字段隐式都是 static 和 final 的。
接口中的方法默认都是 public 的,并且不允许定义为 private 或者 protected。
@@ -636,7 +636,7 @@ System.out.println(InterfaceExample.x);
- 从设计层面上看,抽象类提供了一种 IS-A 关系,那么就必须满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求子类和父类具有 IS-A 关系;
- 从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。
-- 接口的域只能是 static 和 final 类型的,而抽象类的域可以有多种访问权限。
+- 接口的字段只能是 static 和 final 类型的,而抽象类的域可以有多种访问权限。
- 接口的方法只能是 public 的,而抽象类的方法可以由多种访问权限。
**4. 使用选择**
@@ -706,11 +706,11 @@ SuperExtendExample.func()
> [Using the Keyword super](https://docs.oracle.com/javase/tutorial/java/IandI/super.html)
-## 重载与重写
+## 覆盖与重载
-- 重写存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法;
+- 覆盖(Override)存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法;
-- 重载即存在于继承体系中,也存在于同一个类中,指一个方法与已经存在的方法或者父类的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。应该注意的是,返回值不同,其它都相同不算是重载。
+- 重载(Overload)存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。应该注意的是,返回值不同,其它都相同不算是重载。
# 五、String
@@ -739,7 +739,7 @@ SuperExtendExample.func()
如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。
-
+
**3. 安全性**
@@ -773,7 +773,7 @@ String s5 = "bbb";
System.out.println(s4 == s5); // true
```
-Java 虚拟机将堆划分成新生代、老年代和永久代(PermGen Space)。在 Java 6 之前,字符串常量池被放在永久代中,而在 Java 7 时,它被放在堆的其它位置。这是因为永久代的空间有限,如果大量使用字符串的场景下会导致 OutOfMemoryError 错误。
+Java 虚拟机将堆划分成新生代、老年代和永久代(PermGen Space)。在 Java 7 之前,字符串常量池被放在永久代中,而在 Java 7,它被放在堆的其它位置。这是因为永久代的空间有限,如果大量使用字符串的场景下会导致 OutOfMemoryError 错误。
> [What is String interning?](https://stackoverflow.com/questions/10578984/what-is-string-interning) [深入解析 String#intern](https://tech.meituan.com/in_depth_understanding_string_intern.html)
@@ -946,7 +946,7 @@ Throwable 可以用来表示任何可以作为异常抛出的类,分为两种
1. **受检异常** :需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复;
2. **非受检异常** :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序奔溃并且无法恢复。
-
+
> [Java 入门之异常处理](https://www.tianmaying.com/tutorial/Java-Exception) [Java 异常的面试问题及答案 -Part 1](http://www.importnew.com/7383.html)
diff --git a/notes/Java 容器.md b/notes/Java 容器.md
index 7c31b8a2..1cb19fe6 100644
--- a/notes/Java 容器.md
+++ b/notes/Java 容器.md
@@ -567,7 +567,7 @@ static final int DEFAULT_CONCURRENCY_LEVEL = 16;
-### 2. HashEntery 的不可变性
+### 2. HashEntry 的不可变性
HashEntry 中的 key,hash,next 都声明为 final 型。这意味着,不能把节点添加到链接的中间和尾部,也不能在链接的中间和尾部删除节点。这个特性可以保证:在访问某个节点时,这个节点之后的链接不会被改变。这个特性可以大大降低处理链表时的复杂性。
diff --git a/notes/Java 并发.md b/notes/Java 并发.md
index 742d6408..a1131c9c 100644
--- a/notes/Java 并发.md
+++ b/notes/Java 并发.md
@@ -76,7 +76,7 @@
## 无限期等待(Waiting)
-等待其它线程显示地唤醒,否则不会被分配 CPU 时间片。
+等待其它线程显式地唤醒,否则不会被分配 CPU 时间片。
| 进入方法 | 退出方法 |
| --- | --- |
@@ -794,9 +794,10 @@ public class SemaphoreExample {
try {
semaphore.acquire();
System.out.print(semaphore.availablePermits() + " ");
- semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
+ } finally {
+ semaphore.release();
}
});
}
@@ -1413,7 +1414,7 @@ ABA :如果一个变量 V 初次读取的时候是 A 值,它的值被改成
**(二)栈封闭**
-多个线程方法同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在栈中,属于线程私有的。
+多个线程访问同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在栈中,属于线程私有的。
```java
import java.util.concurrent.ExecutorService;
diff --git a/notes/MySQL.md b/notes/MySQL.md
index 99fc6797..5cc1fd69 100644
--- a/notes/MySQL.md
+++ b/notes/MySQL.md
@@ -40,7 +40,7 @@ InnoDB 是 MySQL 默认的事务型存储引擎,只有在需要 InnoDB 不支
## MyISAM
-MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等。但 MyISAM 不支持事务和行级锁,而且崩溃后无法安全恢复。
+MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等。但 MyISAM 不支持事务和行级锁,而且崩溃后无法安全恢复。应该注意的是,MySQL5.6.4 添加了对 InnoDB 引擎的全文索引支持。
只能对整张表加锁,而不是针对行。
@@ -62,7 +62,7 @@ MyISAM 设计简单,数据以紧密格式存储,所以在某些场景下性
2. 备份:InnoDB 支持在线热备份。
3. 崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。
4. 并发:MyISAM 只支持表级锁,而 InnoDB 还支持行级锁。
-5. 其它特性:MyISAM 支持全文索引,地理空间索引。
+5. 其它特性:MyISAM 支持,地理空间索引。
# 二、数据类型
diff --git a/notes/分布式基础.md b/notes/分布式基础.md
index b3ce172e..f7f77498 100644
--- a/notes/分布式基础.md
+++ b/notes/分布式基础.md
@@ -95,7 +95,7 @@
**一致性哈希**
-Distributed Hash Table(DHT):对于哈希空间 0\~2n,将该哈希空间看成一个哈希环,将每个节点都配置到哈希环上。每个数据对象通过哈希取模得到哈希值之后,存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上。
+Distributed Hash Table(DHT):对于哈希空间 [0, 2n-1],将该哈希空间看成一个哈希环,将每个节点都配置到哈希环上。每个数据对象通过哈希取模得到哈希值之后,存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上。
diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md
index 8af879a1..4a6c375c 100644
--- a/notes/剑指 offer 题解.md
+++ b/notes/剑指 offer 题解.md
@@ -82,7 +82,7 @@
# 2. 实现 Singleton
-> [单例模式](https://github.com/CyC2018/Interview- Notebook/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md)
+> [单例模式](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md)
# 3. 数组中重复的数字
@@ -1142,7 +1142,7 @@ public ListNode Merge(ListNode list1, ListNode list2) {
ListNode head = new ListNode(-1);
ListNode cur = head;
while (list1 != null && list2 != null) {
- if (list1.val < list2.val) {
+ if (list1.val <= list2.val) {
cur.next = list1;
list1 = list1.next;
} else {
@@ -1409,7 +1409,7 @@ public ArrayList> Print(TreeNode pRoot) {
## 题目描述
-输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。
+输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。
例如,下图是后序遍历序列 3,1,2 所对应的二叉搜索树。
@@ -1673,36 +1673,30 @@ public ArrayList GetLeastNumbers_Solution(int[] nums, int k) {
int kthSmallest = findKthSmallest(nums, k - 1);
ArrayList ret = new ArrayList<>();
for (int val : nums) {
- if (val <= kthSmallest && ret.size() < k) ret.add(val);
+ if (val <= kthSmallest && ret.size() < k) {
+ ret.add(val);
+ }
}
return ret;
}
public int findKthSmallest(int[] nums, int k) {
- int l = 0;
- int h = nums.length - 1;
+ int l = 0, h = nums.length - 1;
while (l < h) {
int j = partition(nums, l, h);
- if (j < k) {
- l = j + 1;
- } else if (j > k) {
- h = j - 1;
- } else {
- break;
- }
+ if (j == k) break;
+ if (j > k) h = j - 1;
+ else l = j + 1;
}
return nums[k];
}
private int partition(int[] nums, int l, int h) {
- int i = l;
- int j = h + 1;
+ int i = l, j = h + 1;
while (true) {
while (i < h && nums[++i] < nums[l]) ;
while (j > l && nums[l] < nums[--j]) ;
- if (i >= j) {
- break;
- }
+ if (i >= j) break;
swap(nums, i, j);
}
swap(nums, l, j);
@@ -1710,9 +1704,7 @@ private int partition(int[] nums, int l, int h) {
}
private void swap(int[] nums, int i, int j) {
- int t = nums[i];
- nums[i] = nums[j];
- nums[j] = t;
+ int t = nums[i]; nums[i] = nums[j]; nums[j] = t;
}
```
@@ -1882,7 +1874,7 @@ private int getAmountOfDigit(int digit) {
}
/**
- * 在 digit 位数组成的字符串中,第 index 为的数
+ * 在 digit 位数组成的字符串中,第 index 个数
*/
private int digitAtIndex(int index, int digit) {
int number = beginNumber(digit) + index / digit;
@@ -1994,6 +1986,7 @@ public int longestSubStringWithoutDuplication(String str) {
int curLen = 0;
int maxLen = 0;
int[] indexs = new int[26];
+ Arrays.fill(indexs, -1);
for (int i = 0; i < str.length(); i++) {
int c = str.charAt(i) - 'a';
int preIndex = indexs[c];
@@ -2018,21 +2011,19 @@ public int longestSubStringWithoutDuplication(String str) {
## 解题思路
```java
-public int GetUglyNumber_Solution(int N) {
- if (N <= 6) return N;
+public int GetUglyNumber_Solution(int index) {
+ if (index <= 6) return index;
int i2 = 0, i3 = 0, i5 = 0;
- int cnt = 1;
- int[] dp = new int[N];
+ int[] dp = new int[index];
dp[0] = 1;
- while (cnt < N) {
+ for (int i = 1; i < index; i++) {
int n2 = dp[i2] * 2, n3 = dp[i3] * 3, n5 = dp[i5] * 5;
- int min = Math.min(n2, Math.min(n3, n5));
- dp[cnt++] = min;
- if (min == n2) i2++;
- if (min == n3) i3++;
- if (min == n5) i5++;
+ dp[i] = Math.min(n2, Math.min(n3, n5));
+ if (dp[i] == n2) i2++;
+ if (dp[i] == n3) i3++;
+ if (dp[i] == n5) i5++;
}
- return dp[N - 1];
+ return dp[index - 1];
}
```
diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md
index 46b5e1b8..134c60fa 100644
--- a/notes/数据库系统原理.md
+++ b/notes/数据库系统原理.md
@@ -307,7 +307,7 @@ InnoDB 的 MVCC 使用到的快照存储在 Undo 日志中,该日志通过回
### 4. UPDATE
-将系统版本号作为更新后的数据行快照的创建版本号,同时将系统版本号作为作为更新前的数据行快照的删除版本号。可以理解为先执行 DELETE 后执行 INSERT。
+将系统版本号作为更新后的数据行快照的创建版本号,同时将系统版本号作为更新前的数据行快照的删除版本号。可以理解为先执行 DELETE 后执行 INSERT。
## 快照读与当前读
@@ -401,7 +401,7 @@ SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE;
1. 冗余数据,例如学生-2 出现了两次。
2. 修改异常,修改了一个记录中的信息,但是另一个记录中相同的信息却没有被修改。
-3. 删除异常,删除一个信息,那么也会丢失其它信息。例如如果删除了课程-1,需要删除第二行和第三行,那么学生-1 的信息就会丢失。
+3. 删除异常,删除一个信息,那么也会丢失其它信息。例如如果删除了课程-1,需要删除第一行和第三行,那么学生-1 的信息就会丢失。
4. 插入异常,例如想要插入一个学生的信息,如果这个学生还没选课,那么就无法插入。
## 范式
diff --git a/notes/算法.md b/notes/算法.md
index 161c2e79..997dc245 100644
--- a/notes/算法.md
+++ b/notes/算法.md
@@ -1439,7 +1439,7 @@ public class Transaction{
### 3. 基于线性探测法的散列表
-线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。使用线程探测法,数组的大小 M 应当大于键的个数 N(M>N)。
+线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。使用线性探测法,数组的大小 M 应当大于键的个数 N(M>N)。
diff --git a/notes/设计模式.md b/notes/设计模式.md
index 21ce516f..b7e6c76a 100644
--- a/notes/设计模式.md
+++ b/notes/设计模式.md
@@ -276,13 +276,12 @@ public class ConcreteFactory2 extends Factory {
抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂模式只是用于创建一个对象,这和抽象工厂模式有很大不同。
-抽象工厂模式用到了工厂模式来创建单一对象,在类图左部,AbstractFactory 中的 createProductA 和 createProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。
+抽象工厂模式用到了工厂模式来创建单一对象,AbstractFactory 中的 createProductA 和 createProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。
至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。
从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂模式使用了继承。
-
## 代码实现
```java