可以跳过暂存区域直接从分支中取出修改,或者直接提交修改到分支中。
- git commit -a 直接把所有文件的修改添加到暂存区然后执行提交
- git checkout HEAD -- files 取出最后一次修改,可以用来进行回滚操作
+
+
# 分支实现
使用指针将每个提交连接成一条时间线,HEAD 指针指向当前分支指针。
-
+
新建分支是新建一个指针指向时间线的最后一个节点,并让 HEAD 指针指向新分支表示新分支成为当前分支。
-
+
每次提交只会让当前分支指针向前移动,而其它分支指针不会移动。
-
+
合并分支也只需要改变指针即可。
-
+
# 冲突
当两个分支都对同一个文件的同一行进行了修改,在分支合并时就会产生冲突。
-
+
Git 会使用 <<<<<<< ,======= ,>>>>>>> 标记出不同分支的内容,只需要把不同分支中冲突部分修改成一样就能解决冲突。
@@ -88,7 +90,7 @@ Creating a new branch is quick AND simple.
$ git merge --no-ff -m "merge with no-ff" dev
```
-
**3. 安全性**
@@ -640,6 +645,65 @@ SuperExtendExample.func()
应该注意的是,返回值不同,其它都相同不算是重载。
+**3. 实例**
+
+```java
+class A {
+ public String show(D obj) {
+ return ("A and D");
+ }
+
+ public String show(A obj) {
+ return ("A and A");
+ }
+}
+
+class B extends A {
+ public String show(B obj) {
+ return ("B and B");
+ }
+
+ public String show(A obj) {
+ return ("B and A");
+ }
+}
+
+class C extends B {
+}
+
+class D extends B {
+}
+```
+
+```java
+public class Test {
+
+ public static void main(String[] args) {
+ A a1 = new A();
+ A a2 = new B();
+ B b = new B();
+ C c = new C();
+ D d = new D();
+ System.out.println(a1.show(b)); // A and A
+ System.out.println(a1.show(c)); // A and A
+ System.out.println(a1.show(d)); // A and D
+ System.out.println(a2.show(b)); // B and A
+ System.out.println(a2.show(c)); // B and A
+ System.out.println(a2.show(d)); // A and D
+ System.out.println(b.show(b)); // B and B
+ System.out.println(b.show(c)); // B and B
+ System.out.println(b.show(d)); // A and D
+ }
+}
+```
+
+涉及到重写时,方法调用的优先级为:
+
+- this.show(O)
+- super.show(O)
+- this.show((super)O)
+- super.show((super)O)
+
# 五、Object 通用方法
## 概览
diff --git "a/convert/Java \345\256\271\345\231\250.md" "b/convert/Java \345\256\271\345\231\250.md"
index 4d69c98..314c02f 100644
--- "a/convert/Java \345\256\271\345\231\250.md"
+++ "b/convert/Java \345\256\271\345\231\250.md"
@@ -10,7 +10,8 @@ PDF制作github: https://github.com/sjsdfg/CS-Notes-PDF
## Collection
-
+$$
+dp[i]=max(dp[i-2]+nums[i],dp[i-1])
+$$
```java
public int rob(int[] nums) {
@@ -2461,7 +2467,9 @@ private int rob(int[] nums, int first, int last) {
综上所述,错误装信数量方式数量为:
-
$dp[i]=(i-1)*dp[i-2]+(i-1)*dp[i-1]$
+$$
+dp[i]=(i-1)*dp[i-2]+(i-1)*dp[i-1]
+$$
**母牛生产**
@@ -2471,7 +2479,9 @@ private int rob(int[] nums, int first, int last) {
第 i 年成熟的牛的数量为:
-
+$$
+dp[i][j]=\left\{\begin{array}{rcl}dp[i-1][j-1]&&{S1_i==S2_j}\\max(dp[i-1][j],dp[i][j-1])&&{S1_i<>S2_j}\end{array}\right.
+$$
对于长度为 N 的序列 S1 和长度为 M 的序列 S2,dp[N][M] 就是序列 S1 和序列 S2 的最长公共子序列长度。
@@ -2915,7 +2929,9 @@ public int lengthOfLCS(int[] nums1, int[] nums2) {
第 i 件物品可添加也可以不添加,取决于哪种情况下最大价值更大。因此,0-1 背包的状态转移方程为:
-
$dp[i][j]=max(dp[i-1][j],dp[i-1][j-w]+v)$
+$$
+dp[i][j]=max(dp[i-1][j],dp[i-1][j-w]+v)
+$$
```java
public int knapsack(int W, int N, int[] weights, int[] values) {
@@ -2938,7 +2954,9 @@ public int knapsack(int W, int N, int[] weights, int[] values) {
在程序实现时可以对 0-1 背包做优化。观察状态转移方程可以知道,前 i 件物品的状态仅与前 i-1 件物品的状态有关,因此可以将 dp 定义为一维数组,其中 dp[j] 既可以表示 dp[i-1][j] 也可以表示 dp[i][j]。此时,
-
$dp[j]=max(dp[j],dp[j-w]+v)$
+$$
+dp[j]=max(dp[j],dp[j-w]+v)
+$$
因为 dp[j-w] 表示 dp[i-1][j-w],因此不能先求 dp[i][j-w],以防将 dp[i-1][j-w] 覆盖。也就是说要先计算 dp[i][j] 再计算 dp[i][j-w],在程序实现时需要按倒序来循环求解。
@@ -3000,7 +3018,6 @@ public boolean canPartition(int[] nums) {
int W = sum / 2;
boolean[] dp = new boolean[W + 1];
dp[0] = true;
- Arrays.sort(nums);
for (int num : nums) { // 0-1 背包一个物品只能用一次
for (int i = W; i >= num; i--) { // 从后往前,先计算 dp[i] 再计算 dp[i-num]
dp[i] = dp[i] || dp[i - num];
@@ -5645,7 +5662,7 @@ Output: 5
Explanation: The longest harmonious subsequence is [3,2,2,2,3].
```
-和谐序列中最大数和最小数只差正好为 1,应该注意的是序列的元素不一定是数组的连续元素。
+和谐序列中最大数和最小数之差正好为 1,应该注意的是序列的元素不一定是数组的连续元素。
```java
public int findLHS(int[] nums) {
diff --git "a/convert/Leetcode-Database \351\242\230\350\247\243.md" "b/convert/Leetcode-Database \351\242\230\350\247\243.md"
index e43de6b..2838dc3 100644
--- "a/convert/Leetcode-Database \351\242\230\350\247\243.md"
+++ "b/convert/Leetcode-Database \351\242\230\350\247\243.md"
@@ -483,7 +483,7 @@ https://leetcode.com/problems/customers-who-never-order/description/
## Description
-Curstomers 表:
+Customers 表:
```html
+----+-------+
diff --git a/convert/MySQL.md b/convert/MySQL.md
index 59d2c3f..8599c12 100644
--- a/convert/MySQL.md
+++ b/convert/MySQL.md
@@ -16,7 +16,7 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具
在 B+ Tree 中,一个节点中的 key 从左到右非递减排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,且不为 null,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1。
-
+
### 2. 操作
@@ -58,11 +58,11 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具
InnoDB 的 B+Tree 索引分为主索引和辅助索引。主索引的叶子节点 data 域记录着完整的数据记录,这种索引方式被称为聚簇索引。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
-
+
辅助索引的叶子节点的 data 域记录着主键的值,因此在使用辅助索引进行查找时,需要先查找到主键值,然后再到主索引中进行查找。
-
+
### 2. 哈希索引
diff --git a/convert/Socket.md b/convert/Socket.md
index 82d7626..6365b9c 100644
--- a/convert/Socket.md
+++ b/convert/Socket.md
@@ -23,11 +23,11 @@ Unix 有五种 I/O 模型:
## 阻塞式 I/O
-应用进程被阻塞,直到数据复制到应用进程缓冲区中才返回。
+应用进程被阻塞,直到数据从内核缓冲区复制到应用进程缓冲区中才返回。
-应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,所以不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。
+应该注意到,在阻塞的过程中,其它应用进程还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其它应用进程还可以执行,所以不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。
-下图中,recvfrom 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。
+下图中,recvfrom() 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。
```c
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
@@ -39,7 +39,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。
-由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率是比较低的。
+由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率比较低。
## 一致性
@@ -169,7 +169,6 @@ BASE 是基本可用(Basically Available)、软状态(Soft State)和最
BASE 理论是对 CAP 中一致性和可用性权衡的结果,它的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
-
+
```java
// 缓存中序遍历数组每个值对应的索引
private Map indexForInOrders = new HashMap<>();
@@ -324,11 +298,11 @@ public class TreeLinkNode {
① 如果一个节点的右子树不为空,那么该节点的下一个节点是右子树的最左节点;
-
+
② 否则,向上找第一个左链接指向的树包含该节点的祖先节点。
-
+
```java
public TreeLinkNode GetNext(TreeLinkNode pNode) {
@@ -361,7 +335,8 @@ public TreeLinkNode GetNext(TreeLinkNode pNode) {
in 栈用来处理入栈(push)操作,out 栈用来处理出栈(pop)操作。一个元素进入 in 栈之后,出栈的顺序被反转。当元素要出栈时,需要先进入 out 栈,此时元素出栈顺序再一次被反转,因此出栈顺序就和最开始入栈顺序是相同的,先进入的元素先退出,这就是队列的顺序。
-
+
+
```java
Stack in = new Stack();
@@ -391,13 +366,16 @@ public int pop() throws Exception {
求斐波那契数列的第 n 项,n <= 39。
-
+
## 解题思路
```java
@@ -2794,6 +2794,8 @@ public int LastRemaining_Solution(int n, int m) {
可以有一次买入和一次卖出,那么买入必须在前。求最大收益。
+
+
## 解题思路
使用贪心策略,假设第 i 轮进行卖出操作,买入操作价格应该在 i 之前并且价格最低。
@@ -2864,6 +2866,8 @@ public int Add(int a, int b) {
给定一个数组 A[0, 1,..., n-1],请构建一个数组 B[0, 1,..., n-1],其中 B 中的元素 B[i]=A[0]\*A[1]\*...\*A[i-1]\*A[i+1]\*...\*A[n-1]。要求不能使用除法。
+
+
# 二、使用场景
diff --git "a/convert/\347\256\227\346\263\225.md" "b/convert/\347\256\227\346\263\225.md"
index 604f046..eec6ff2 100644
--- "a/convert/\347\256\227\346\263\225.md"
+++ "b/convert/\347\256\227\346\263\225.md"
@@ -260,7 +260,7 @@ public abstract class Sort> {
选择排序需要 \~N2/2 次比较和 \~N 次交换,它的运行时间与输入无关,这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作。
-
+
```java
public class Selection> extends Sort {
@@ -287,9 +287,7 @@ public class Selection> extends Sort {
在一轮循环中,如果没有发生交换,就说明数组已经是有序的,此时可以直接退出。
-以下演示了在一轮循环中,将最大的元素 5 上浮到最右侧。
-
-
+
```java
public class Bubble> extends Sort {
@@ -325,7 +323,7 @@ public class Bubble> extends Sort {
以下演示了在一轮循环中,将元素 2 插入到左侧已经排序的数组中。
-
+
```java
public class Insertion> extends Sort {
@@ -350,7 +348,7 @@ public class Insertion> extends Sort {
希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。
-
+
```java
public class Shell> extends Sort {
@@ -384,7 +382,7 @@ public class Shell> extends Sort {
归并排序的思想是将数组分成两部分,分别进行排序,然后归并起来。
-
+
### 1. 归并方法
@@ -411,7 +409,7 @@ public abstract class MergeSort> extends Sort {
} else if (j > h) {
nums[k] = aux[i++];
- } else if (aux[i].compareTo(nums[j]) <= 0) {
+ } else if (aux[i].compareTo(aux[j]) <= 0) {
nums[k] = aux[i++]; // 先进行这一步,保证稳定性
} else {
@@ -479,7 +477,7 @@ public class Down2UpMergeSort> extends MergeSort {
- 归并排序将数组分为两个子数组分别排序,并将有序的子数组归并使得整个数组排序;
- 快速排序通过一个切分元素将数组分为两个子数组,左子数组小于等于切分元素,右子数组大于等于切分元素,将这两个子数组排序也就将整个数组排序了。
-
+
```java
public class QuickSort> extends Sort {
@@ -510,7 +508,7 @@ public class QuickSort> extends Sort {
取 a[l] 作为切分元素,然后从数组的左端向右扫描直到找到第一个大于等于它的元素,再从数组的右端向左扫描找到第一个小于它的元素,交换这两个元素。不断进行这个过程,就可以保证左指针 i 的左侧元素都不大于切分元素,右指针 j 的右侧元素都不小于切分元素。当两个指针相遇时,将切分元素 a[l] 和 a[j] 交换位置。
-
+
```java
private int partition(T[] nums, int l, int h) {
@@ -614,7 +612,7 @@ public T select(T[] nums, int k) {
堆可以用数组来表示,这是因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。
-
+
```java
public class Heap> {
@@ -650,7 +648,7 @@ public class Heap> {
在堆中,当一个节点比父节点大,那么需要交换这个两个节点。交换后还可能比它新的父节点大,因此需要不断地进行比较和交换操作,把这种操作称为上浮。
-
```java
private void sink(int k) {
@@ -712,15 +710,13 @@ public T delMax() {
无序数组建立堆最直接的方法是从左到右遍历数组进行上浮操作。一个更高效的方法是从右至左进行下沉操作,如果一个节点的两个节点都已经是堆有序,那么进行下沉操作可以使得这个节点为根节点的堆有序。叶子节点不需要进行下沉操作,可以忽略叶子节点的元素,因此只需要遍历一半的元素即可。
-
+
#### 5.2 交换堆顶元素与最后一个元素
交换之后需要进行下沉操作维持堆的有序状态。
-
-
-
+
```java
public class HeapSort> extends Sort {
@@ -2013,7 +2009,7 @@ public class Transaction {
对于 N 个键,M 条链表 (N>M),如果哈希函数能够满足均匀性的条件,每条链表的大小趋向于 N/M,因此未命中的查找和插入操作所需要的比较次数为 \~N/M。
-
+
### 3. 线性探测法
@@ -2021,7 +2017,7 @@ public class Transaction {
使用线性探测法,数组的大小 M 应当大于键的个数 N(M>N)。
-
+
```java
public class LinearProbingHashST implements UnorderedST {
@@ -2122,7 +2118,7 @@ public void delete(Key key) {
线性探测法的成本取决于连续条目的长度,连续条目也叫聚簇。当聚簇很长时,在查找和插入时也需要进行很多次探测。例如下图中 2\~5 位置就是一个聚簇。
-
+$$
+\frac{1}{m}\vec{S}\cdot\vec{S'}=-1
+$$
-其中 $\vec{S'}$ 为 $\vec{S}$ 的反码。
+其中 为 的反码。
-利用上面的式子我们知道,当接收端使用码片 $\vec{S}$ 对接收到的数据进行内积运算时,结果为 0 的是其它用户发送的数据,结果为 1 的是用户发送的比特 1,结果为 -1 的是用户发送的比特 0。
+利用上面的式子我们知道,当接收端使用码片 对接收到的数据进行内积运算时,结果为 0 的是其它用户发送的数据,结果为 1 的是用户发送的比特 1,结果为 -1 的是用户发送的比特 0。
码分复用需要发送的数据量为原先的 m 倍。
@@ -281,7 +294,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标
正是由于这种自学习能力,因此交换机是一种即插即用设备,不需要网络管理员手动配置交换表内容。
-下图中,交换机有 4 个接口,主机 A 向主机 B 发送数据帧时,交换机把主机 A 到接口 1 的映射写入交换表中。为了发送数据帧到 B,先查交换表,此时没有主机 B 的表项,那么主机 A 就发送广播帧,主机 C 和主机 D 会丢弃该帧。主机 B 向主机 A 发送数据包时,交换机查找交换表得到主机 A 映射的接口为 1,就发送数据帧到接口 1,同时交换机添加主机 B 到接口 3 的映射。
+下图中,交换机有 4 个接口,主机 A 向主机 B 发送数据帧时,交换机把主机 A 到接口 1 的映射写入交换表中。为了发送数据帧到 B,先查交换表,此时没有主机 B 的表项,那么主机 A 就发送广播帧,主机 C 和主机 D 会丢弃该帧,主机 B 回应该帧向主机 A 发送数据包时,交换机查找交换表得到主机 A 映射的接口为 1,就发送数据帧到接口 1,同时交换机添加主机 B 到接口 2 的映射。