diff --git a/notes/Java 基础.md b/notes/Java 基础.md
index 9da25851..eb3572cd 100644
--- a/notes/Java 基础.md
+++ b/notes/Java 基础.md
@@ -216,7 +216,7 @@ System.out.println(s3 == s4); // true
```java
String s5 = "bbb";
String s6 = "bbb";
-System.out.println(s4 == s5); // true
+System.out.println(s5 == s6); // true
```
在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。
@@ -226,9 +226,9 @@ System.out.println(s4 == s5); // true
## new String("abc")
-使用这种方式一共会创建两个字符串对象(前提是 String Poll 中还没有 "abc" 字符串对象)。
+使用这种方式一共会创建两个字符串对象(前提是 String Pool 中还没有 "abc" 字符串对象)。
-- "abc" 属于字符串字面量,因此编译时期会在 String Poll 中创建一个字符串对象,指向这个 "abc" 字符串字面量;
+- "abc" 属于字符串字面量,因此编译时期会在 String Pool 中创建一个字符串对象,指向这个 "abc" 字符串字面量;
- 而使用 new 的方式会在堆中创建一个字符串对象。
创建一个测试类,其 main 方法中使用这种方式来创建字符串对象。
@@ -267,7 +267,7 @@ Constant pool:
// ...
```
-在 Constant Poll 中,#19 存储这字符串字面量 "abc",#3 是 String Poll 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Poll 中的字符串对象作为 String 构造函数的参数。
+在 Constant Pool 中,#19 存储这字符串字面量 "abc",#3 是 String Pool 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Pool 中的字符串对象作为 String 构造函数的参数。
以下是 String 构造函数的源码,可以看到,在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组。
@@ -368,10 +368,11 @@ short s1 = 1;
// s1 = s1 + 1;
```
-但是使用 += 运算符可以执行隐式类型转换。
+但是使用 += 或者 ++ 运算符可以执行隐式类型转换。
```java
s1 += 1;
+// s1++;
```
上面的语句相当于将 s1 + 1 的计算结果进行了向下转型:
diff --git a/notes/Java 容器.md b/notes/Java 容器.md
index 84189928..e42a42f0 100644
--- a/notes/Java 容器.md
+++ b/notes/Java 容器.md
@@ -738,7 +738,7 @@ HashMap 构造函数允许用户传入的容量不是 2 的 n 次方,因为它
```
mask |= mask >> 1 11011000
-mask |= mask >> 2 11111100
+mask |= mask >> 2 11111110
mask |= mask >> 4 11111111
```
diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md
index 04a751c7..def70c60 100644
--- a/notes/Leetcode 题解.md
+++ b/notes/Leetcode 题解.md
@@ -2420,21 +2420,13 @@ public int climbStairs(int n) {
```java
public int rob(int[] nums) {
- int n = nums.length;
- if (n == 0) {
- return 0;
- }
- if (n == 1) {
- return nums[0];
- }
- int pre3 = 0, pre2 = 0, pre1 = 0;
- for (int i = 0; i < n; i++) {
- int cur = Math.max(pre2, pre3) + nums[i];
- pre3 = pre2;
+ int pre2 = 0, pre1 = 0;
+ for (int i = 0; i < nums.length; i++) {
+ int cur = Math.max(pre2 + nums[i], pre1);
pre2 = pre1;
pre1 = cur;
}
- return Math.max(pre1, pre2);
+ return pre1;
}
```
@@ -2443,7 +2435,7 @@ public int rob(int[] nums) {
[213. House Robber II (Medium)](https://leetcode.com/problems/house-robber-ii/description/)
```java
-public int rob(int[] nums) {
+public int rob(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
@@ -2454,15 +2446,14 @@ public int rob(int[] nums) {
return Math.max(rob(nums, 0, n - 2), rob(nums, 1, n - 1));
}
-private int rob(int[] nums, int first, int last) {
- int pre3 = 0, pre2 = 0, pre1 = 0;
+private int rob(int[] nums, int first, int last) {
+ int pre2 = 0, pre1 = 0;
for (int i = first; i <= last; i++) {
- int cur = Math.max(pre3, pre2) + nums[i];
- pre3 = pre2;
+ int cur = Math.max(pre1, pre2 + nums[i]);
pre2 = pre1;
pre1 = cur;
}
- return Math.max(pre2, pre1);
+ return pre1;
}
```
@@ -7063,4 +7054,3 @@ public int[] countBits(int num) {
- 何海涛, 软件工程师. 剑指 Offer: 名企面试官精讲典型编程题[M]. 电子工业出版社, 2014.
- 《编程之美》小组. 编程之美[M]. 电子工业出版社, 2008.
- 左程云. 程序员代码面试指南[M]. 电子工业出版社, 2015.
-
diff --git a/notes/MySQL.md b/notes/MySQL.md
index 2c5d8935..f5479685 100644
--- a/notes/MySQL.md
+++ b/notes/MySQL.md
@@ -374,7 +374,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
### 2. 连接
-可以将原来的连接分解成多个单表连接查询,然后在用户程序中进行连接。
+可以将原来的连接分解成多个单表查询,然后在用户程序中进行连接。
### 3. ID 唯一性
diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md
index 2c8f2822..e1a87b5b 100644
--- a/notes/剑指 offer 题解.md
+++ b/notes/剑指 offer 题解.md
@@ -1154,11 +1154,11 @@ public ListNode FindKthToTail(ListNode head, int k) {
## 解题思路
-使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 z1 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。
+使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 y6 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。
在相遇点,slow 要到环的入口点还需要移动 z 个节点,如果让 fast 重新从头开始移动,并且速度变为每次移动一个节点,那么它到环入口点还需要移动 x 个节点。在上面已经推导出 x=z,因此 fast 和 slow 将在环入口点相遇。
-
+
```java
public ListNode EntryNodeOfLoop(ListNode pHead) {
@@ -1559,7 +1559,7 @@ public ArrayList> Print(TreeNode pRoot) {
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。
-例如,下图是后序遍历序列 3,1,2 所对应的二叉搜索树。
+例如,下图是后序遍历序列 1,3,2 所对应的二叉搜索树。
diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md
index 1bcd2533..1ce774fa 100644
--- a/notes/数据库系统原理.md
+++ b/notes/数据库系统原理.md
@@ -294,12 +294,12 @@ SELECT ... FOR UPDATE;
----
-| 隔离级别 | 脏读 | 不可重复读 | 幻影读 |
-| :---: | :---: | :---:| :---: |
-| 未提交读 | √ | √ | √ |
-| 提交读 | × | √ | √ |
-| 可重复读 | × | × | √ |
-| 可串行化 | × | × | × |
+| 隔离级别 | 脏读 | 不可重复读 | 幻影读 | 加锁读 |
+| :---: | :---: | :---:| :---: | :---: |
+| 未提交读 | √ | √ | √ | × |
+| 提交读 | × | √ | √ | × |
+| 可重复读 | × | × | √ | × |
+| 可串行化 | × | × | × | √ |
# 五、多版本并发控制
diff --git a/notes/算法.md b/notes/算法.md
index cb83830b..1bc0690a 100644
--- a/notes/算法.md
+++ b/notes/算法.md
@@ -459,7 +459,7 @@ public abstract class MergeSort> extends Sort {
将一个大数组分成两个小数组去求解。
-因为每次都将问题对半分成两个子问题,而这种对半分的算法复杂度一般为 O(NlogN),因此该归并排序方法的时间复杂度也为 O(NlogN)。
+因为每次都将问题对半分成两个子问题,这种对半分的算法复杂度一般为 O(NlogN)。
```java
public class Up2DownMergeSort> extends MergeSort {
@@ -617,7 +617,7 @@ public class ThreeWayQuickSort> extends QuickSort {
可以利用这个特性找出数组的第 k 个元素。
-该算法是线性级别的,因为每次能将数组二分,那么比较的总次数为 (N+N/2+N/4+..),直到找到第 k 个元素,这个和显然小于 2N。
+该算法是线性级别的,假设每次能将数组二分,那么比较的总次数为 (N+N/2+N/4+..),直到找到第 k 个元素,这个和显然小于 2N。
```java
public T select(T[] nums, int k) {
@@ -2292,7 +2292,7 @@ from H1 to H3
可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码采用了贪心策略,使出现频率最高的字符的编码最短,从而保证整体的编码长度最短。
-首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点在树的最底层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。
+首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点位于树的更低层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。
生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到叶子节点,叶子节点代表的字符的编码就是这个路径编码。
diff --git a/notes/系统设计基础.md b/notes/系统设计基础.md
index 4a961140..ffa5de70 100644
--- a/notes/系统设计基础.md
+++ b/notes/系统设计基础.md
@@ -4,6 +4,7 @@
* [三、扩展性](#三扩展性)
* [四、可用性](#四可用性)
* [五、安全性](#五安全性)
+* [参考资料](#参考资料)
@@ -102,3 +103,7 @@
# 五、安全性
要求系统的应对各种攻击手段时能够有可靠的应对措施。
+
+# 参考资料
+
+- 大型网站技术架构:核心原理与案例分析
diff --git a/notes/缓存.md b/notes/缓存.md
index 8f7449bf..07a9e866 100644
--- a/notes/缓存.md
+++ b/notes/缓存.md
@@ -99,7 +99,7 @@ public class LRU implements Iterable {
if (map.size() > maxSize) {
Node toRemove = removeTail();
- map.remove(toRemove);
+ map.remove(toRemove.k);
}
}
@@ -114,6 +114,7 @@ public class LRU implements Iterable {
private void appendHead(Node node) {
node.next = head.next;
+ node.next.pre = node;
node.pre = head;
head.next = node;
}
@@ -122,6 +123,7 @@ public class LRU implements Iterable {
private Node removeTail() {
Node node = tail.pre;
tail.pre = node.pre;
+ node.pre.next = tail;
return node;
}
diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md
index e6c462a6..c0c4364e 100644
--- a/notes/计算机操作系统.md
+++ b/notes/计算机操作系统.md
@@ -1038,7 +1038,7 @@ gcc -o hello hello.c
## 静态链接
-静态连接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:
+静态链接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:
- 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
- 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。
diff --git a/notes/设计模式.md b/notes/设计模式.md
index d44d0e33..c177ff92 100644
--- a/notes/设计模式.md
+++ b/notes/设计模式.md
@@ -177,7 +177,7 @@ public class Singleton {
#### Ⅵ 枚举实现
- ```java
+```java
public enum Singleton {
INSTANCE;
@@ -217,7 +217,7 @@ public enum Singleton {
}
}
}
- ```
+```
该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。
@@ -276,6 +276,7 @@ public class ConcreteProduct2 implements Product {
```java
public class Client {
+
public static void main(String[] args) {
int type = 1;
Product product;
@@ -295,6 +296,7 @@ public class Client {
```java
public class SimpleFactory {
+
public Product createProduct(int type) {
if (type == 1) {
return new ConcreteProduct1();
@@ -308,6 +310,7 @@ public class SimpleFactory {
```java
public class Client {
+
public static void main(String[] args) {
SimpleFactory simpleFactory = new SimpleFactory();
Product product = simpleFactory.createProduct(1);
diff --git a/pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png b/pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png
new file mode 100644
index 00000000..0d28e996
Binary files /dev/null and b/pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png differ