Merge pull request #2 from CyC2018/master

update
This commit is contained in:
Peter Ma
2019-02-05 01:51:40 -08:00
committed by GitHub
92 changed files with 180 additions and 363 deletions

View File

@ -1,5 +1,5 @@
[🎉 面试进阶专栏已上线](https://xiaozhuanlan.com/CyC2018)
> [🍉 点击订阅面试进阶专栏](https://xiaozhuanlan.com/CyC2018)
## ✏️ 算法
@ -18,7 +18,7 @@
> [HTTP](notes/HTTP.md) </br>
> [Socket](notes/Socket.md)
## 👫 面向对象
## 🔓 面向对象
> [设计模式](notes/设计模式.md) </br>
> [面向对象思想](notes/面向对象思想.md)
@ -48,7 +48,7 @@
> [缓存](notes/缓存.md) </br>
> [消息队列](notes/消息队列.md)
## 🔨 工具
## 🔧 工具
> [Git](notes/Git.md) </br>
> [Docker](notes/Docker.md) </br>

View File

@ -2,11 +2,7 @@
# CS-Notes
> Computer Sicence Learning Notes.
- Algorithm
- Computer Networks
- ...
- 本项目包含了技术面试必备的基础知识,浅显易懂,你不需要花很长的时间去阅读和理解成堆的技术书籍就可以快速掌握这些知识,从而节省宝贵的面试复习时间。你也可以订阅 <a href="https://xiaozhuanlan.com/CyC2018">面试进阶专栏</a>,包含了学习指导和面试技巧,让你更轻松拿到满意的 Offer。
<span id="busuanzi_container_site_pv">Site View : <span id="busuanzi_value_site_pv">

View File

@ -3,6 +3,10 @@
display: none;
}
#main>ul:nth-child(2) {
display: none;
}
.markdown-section h1 {
margin: 3rem 0 2rem 0;
}
@ -36,4 +40,12 @@ body {
/*.anchor span {
color: rgb(66, 185, 131);
}*/
}*/
section.cover h1 {
margin: 0;
}
body>section>div.cover-main>ul>li>a {
color: #42b983;
}

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、解决的问题](#一解决的问题)
* [二、与虚拟机的比较](#二与虚拟机的比较)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [集中式与分布式](#集中式与分布式)
* [中心服务器](#中心服务器)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一 、基础概念](#一-基础概念)
* [URI](#uri)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、概览](#一概览)
* [二、磁盘操作](#二磁盘操作)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、数据类型](#一数据类型)
* [包装类型](#包装类型)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、概览](#一概览)
* [Collection](#collection)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、线程状态转换](#一线程状态转换)
* [新建New](#新建new)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、运行时数据区域](#一运行时数据区域)
* [程序计数器](#程序计数器)
@ -31,7 +31,7 @@
# 一、运行时数据区域
<div align="center"> <img src="pics/ab701824-e308-4284-88b6-596cc606fadb.png" width="450"/> </div><br>
<div align="center"> <img src="pics/11548742157520.gif" width="450"/> </div><br>
## 程序计数器
@ -41,7 +41,7 @@
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
<div align="center"> <img src="pics/28ab96b4-82ea-4d99-99fb-b320f60d0a58.png" width="500"/> </div><br>
<div align="center"> <img src="pics/11548741556940.gif" width="500"/> </div><br>
可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小:
@ -60,7 +60,8 @@ java -Xss512M HackTheJava
本地方法一般是用其它语言C、C++ 或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序,对待这些方法需要特别处理。
<div align="center"> <img src="pics/JNI-Java-Native-Interface.jpg" width="350"/> </div><br>
<div align="center"> <img src="pics/11548742010310.gif"/> </div><br>
## 堆
@ -73,7 +74,7 @@ java -Xss512M HackTheJava
堆不需要连续内存,并且可以动态增加其内存,增加失败会抛出 OutOfMemoryError 异常。
可以通过 -Xms 和 -Xmx 两个虚拟机参数来指定一个程序的堆内存大小,第一个参数设置初始值,第二个参数设置最大值。
可以通过 -Xms 和 -Xmx 两个虚拟机参数来指定一个程序的堆内存大小,第一个参数设置初始值,第二个参数设置最大值。
```java
java -Xms1M -Xmx2M HackTheJava
@ -99,7 +100,7 @@ Class 文件中的常量池(编译器生成的字面量和符号引用)会
## 直接内存
在 JDK 1.4 中新入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,然后通过 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在堆内存和堆外内存来回拷贝数据。
在 JDK 1.4 中新入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,然后通过 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在堆内存和堆外内存来回拷贝数据。
# 二、垃圾收集
@ -113,25 +114,25 @@ Class 文件中的常量池(编译器生成的字面量和符号引用)会
为对象添加一个引用计数器,当对象增加一个引用时计数器加 1引用失效时计数器减 1。引用计数为 0 的对象可被回收。
两个对象出现循环引用的情况下,此时引用计数器永远不为 0导致无法对它们进行回收。正因为循环引用的存在因此 Java 虚拟机不使用引用计数算法。
两个对象出现循环引用的情况下,此时引用计数器永远不为 0导致无法对它们进行回收。正因为循环引用的存在因此 Java 虚拟机不使用引用计数算法。
```java
public class ReferenceCountingGC {
public class Test {
public Object instance = null;
public static void main(String[] args) {
ReferenceCountingGC objectA = new ReferenceCountingGC();
ReferenceCountingGC objectB = new ReferenceCountingGC();
objectA.instance = objectB;
objectB.instance = objectA;
Test a = new Test();
Test b = new Test();
a.instance = b;
b.instance = a;
}
}
```
### 2. 可达性分析算法
通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是存活的,不可达的对象可被回收。
GC Roots 作为起始点进行搜索,可达的对象都是存活的,不可达的对象可被回收。
Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC Roots 一般包含以下内容:
@ -140,11 +141,11 @@ Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC
- 方法区中类静态属性引用的对象
- 方法区中的常量引用的对象
<div align="center"> <img src="pics/0635cbe8.png" width=""/> </div><br>
<div align="center"> <img src="pics/11548742505541.gif"/> </div><br>
### 3. 方法区的回收
因为方法区主要存放永久代对象,而永久代对象的回收率比新生代低很多,因此在方法区上进行回收性价比不高。
因为方法区主要存放永久代对象,而永久代对象的回收率比新生代低很多,所以在方法区上进行回收性价比不高。
主要是对常量池的回收和对类的卸载。
@ -158,9 +159,9 @@ Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC
### 4. finalize()
finalize() 类似 C++ 的析构函数,用于关闭外部资源。但是 try-finally 等方式可以做的更好,并且该方法运行代价很高,不确定性大,无法保证各个对象的调用顺序,因此最好不要使用。
类似 C++ 的析构函数用于关闭外部资源。try-finally 等方式可以做的更好,并且该方法运行代价很高,不确定性大,无法保证各个对象的调用顺序,因此最好不要使用。
当一个对象可被回收时,如果需要执行该对象的 finalize() 方法,那么就有可能在该方法中让对象重新被引用,从而实现自救。自救只能进行一次,如果回收的对象之前调用了 finalize() 方法自救,后面回收时不会调用 finalize() 方法。
当一个对象可被回收时,如果需要执行该对象的 finalize() 方法,那么就有可能在该方法中让对象重新被引用,从而实现自救。自救只能进行一次,如果回收的对象之前调用了 finalize() 方法自救,后面回收时不会调用方法。
## 引用类型
@ -194,7 +195,7 @@ obj = null; // 使对象只被软引用关联
被弱引用关联的对象一定会被回收,也就是说它只能存活到下一次垃圾回收发生之前。
使用 WeakReference 类来实现弱引用。
使用 WeakReference 类来创建弱引用。
```java
Object obj = new Object();
@ -208,7 +209,7 @@ obj = null;
为一个对象设置虚引用的唯一目的是能在这个对象被回收时收到一个系统通知。
使用 PhantomReference 来实现虚引用。
使用 PhantomReference 来创建虚引用。
```java
Object obj = new Object();
@ -220,7 +221,7 @@ obj = null;
### 1. 标记 - 清除
<div align="center"> <img src="pics/a4248c4b-6c1d-4fb8-a557-86da92d3a294.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/11548743021625.gif"/> </div><br>
标记要回收的对象,然后清除。
@ -231,21 +232,21 @@ obj = null;
### 2. 标记 - 整理
<div align="center"> <img src="pics/902b83ab-8054-4bd2-898f-9a4a0fe52830.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/11548743193273.gif"/> </div><br>
让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
### 3. 复制
<div align="center"> <img src="pics/e6b733ad-606d-4028-b3e8-83c3a73a3797.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/11548743457272.gif"/> </div><br>
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。
主要不足是只使用了内存的一半。
现在的商业虚拟机都采用这种收集算法回收新生代,但是并不是划分为大小相等的两块,而是一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时将 Eden 和 Survivor 中还存活着的对象全部复制到另一块 Survivor 空间上,最后清理 Eden 和使用过的那一块 Survivor。
现在的商业虚拟机都采用这种收集算法回收新生代,但是并不是划分为大小相等的两块,而是一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中一块 Survivor。在回收时将 Eden 和 Survivor 中还存活着的对象全部复制到另一块 Survivor 上,最后清理 Eden 和使用过的那一块 Survivor。
HotSpot 虚拟机的 Eden 和 Survivor 大小比例默认为 8:1保证了内存的利用率达到 90%。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,此时需要依赖于老年代进行空间分配担保,也就是借用老年代的空间存储放不下的对象。
HotSpot 虚拟机的 Eden 和 Survivor 大小比例默认为 8:1保证了内存的利用率达到 90%。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 就不够用了,此时需要依赖于老年代进行空间分配担保,也就是借用老年代的空间存储放不下的对象。
### 4. 分代收集
@ -262,7 +263,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1保证了
以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。
- 单线程与多线程:单线程指的是垃圾收集器只使用一个线程进行收集,而多线程使用多个线程;
- 单线程与多线程:单线程指的是垃圾收集器只使用一个线程,而多线程使用多个线程;
- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并行指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。
### 1. Serial 收集器
@ -275,7 +276,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
它的优点是简单高效,对于单个 CPU 环境来说,由于没有线程交互的开销,因此拥有最高的单线程收集效率。
它是 Client 模式下的默认新生代收集器,因为在该应用场景下内存一般来说不会很大。Serial 收集器收集几十兆甚至一两百兆的新生代停顿时间可以控制在一百多毫秒以内,只要不是太频繁,这点停顿是可以接受的。
它是 Client 模式下的默认新生代收集器,因为在该应用场景下内存一般来说不会很大。收集几十兆甚至一两百兆的新生代停顿时间可以控制在一百多毫秒以内,只要不是太频繁,这点停顿时间是可以接受的。
### 2. ParNew 收集器
@ -285,8 +286,6 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
是 Server 模式下首选的新生代收集器,除了性能原因外,主要是因为除了 Serial 收集器,只有它能与 CMS 收集器配合工作。
默认开启的线程数量与 CPU 数量相同,可以使用 -XX:ParallelGCThreads 参数来设置线程数。
### 3. Parallel Scavenge 收集器
与 ParNew 一样是多线程收集器。
@ -441,7 +440,7 @@ G1 把堆划分成多个大小相等的独立区域Region新生代和
## 类的生命周期
<div align="center"> <img src="pics/32b8374a-e822-4720-af0b-c0f485095ea2.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/11548744140733.gif"/> </div><br>
包括以下 7 个阶段:
@ -583,7 +582,7 @@ System.out.println(ConstClass.HELLOWORLD);
## 类与类加载器
两个类相等需要类本身相等,并且使用同一个类加载器进行加载。这是因为每一个类加载器都拥有一个独立的类名称空间。
两个类相等需要类本身相等,并且使用同一个类加载器进行加载。这是因为每一个类加载器都拥有一个独立的类名称空间。
这里的相等,包括类的 Class 对象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回结果为 true也包括使用 instanceof 关键字做对象所属关系判定结果为 true。
@ -591,9 +590,9 @@ System.out.println(ConstClass.HELLOWORLD);
从 Java 虚拟机的角度来讲,只存在以下两种不同的类加载器:
- 启动类加载器Bootstrap ClassLoader这个类加载器用 C++ 实现,是虚拟机自身的一部分;
- 启动类加载器Bootstrap ClassLoader使用 C++ 实现,是虚拟机自身的一部分;
- 所有其类的加载器,这些类由 Java 实现,独立于虚拟机外部,并且全都继承自抽象类 java.lang.ClassLoader。
- 所有其类的加载器,使用 Java 实现,独立于虚拟机继承自抽象类 java.lang.ClassLoader。
从 Java 开发人员的角度看,类加载器可以划分得更细致一些:
@ -607,13 +606,13 @@ System.out.println(ConstClass.HELLOWORLD);
应用程序都是由三种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。
下图展示的类加载器之间的层次关系称为类加载器的双亲委派模型Parents Delegation Model。该模型要求除了顶层的启动类加载器外其余的类加载器都有自己的父类加载器。这里类加载器之间的父子关系一般通过组合Composition关系来实现而不是通过继承Inheritance的关系实现。
下图展示的类加载器之间的层次关系称为类加载器的双亲委派模型Parents Delegation Model。该模型要求除了顶层的启动类加载器外其余的类加载器都有自己的父类加载器。这里类加载器之间的父子关系一般通过组合Composition关系来实现而不是通过继承Inheritance的关系实现。
<div align="center"> <img src="pics/class_loader_hierarchy.png" width="600"/> </div><br>
### 1. 工作过程
一个类加载器首先将类加载请求传送到父类加载器,只有当父类加载器无法完成类加载请求时才尝试加载。
一个类加载器首先将类加载请求传送到父类加载器,只有当父类加载器无法完成类加载请求时才尝试自己加载。
### 2. 好处

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [算法思想](#算法思想)
* [双指针](#双指针)
@ -3050,7 +3050,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];
@ -5695,7 +5694,7 @@ Output: 5
Explanation: The longest harmonious subsequence is [3,2,2,2,3].
```
和谐序列中最大数和最小数差正好为 1应该注意的是序列的元素不一定是数组的连续元素。
和谐序列中最大数和最小数差正好为 1应该注意的是序列的元素不一定是数组的连续元素。
```java
public int findLHS(int[] nums) {

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [595. Big Countries](#595-big-countries)
* [627. Swap Salary](#627-swap-salary)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、常用操作以及概念](#一常用操作以及概念)
* [快捷键](#快捷键)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、索引](#一索引)
* [B+ Tree 原理](#b-tree-原理)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、概述](#一概述)
* [二、数据类型](#二数据类型)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、基础](#一基础)
* [二、创建表](#二创建表)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、I/O 模型](#一io-模型)
* [阻塞式 I/O](#阻塞式-io)

BIN
docs/notes/pics/1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、可读性的重要性](#一可读性的重要性)
* [二、用名字表达代码含义](#二用名字表达代码含义)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
<!-- GFM-TOC -->

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、分布式锁](#一分布式锁)
* [数据库的唯一索引](#数据库的唯一索引)

View File

@ -1,7 +1,5 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [1. 前言](#1-前言)
* [2. 实现 Singleton](#2-实现-singleton)
* [3. 数组中重复的数字](#3-数组中重复的数字)
* [4. 二维数组中的查找](#4-二维数组中的查找)
* [5. 替换空格](#5-替换空格)
@ -82,21 +80,6 @@
<!-- GFM-TOC -->
# 1. 前言
本文的绘图可通过以下途径免费获得并使用:
- [ProcessOn](https://www.processon.com/view/5a3e4c7be4b0909c1aa18b49)
- [DrawIO](https://drive.google.com/file/d/1nSSCpPUC05MFoeFuf_aeTtkm7dG5-bJ1/view?usp=sharing)
本文内容可在微信小程序中阅读:
<div align="center"> <img src="pics/gh_a68199af85d6_258_20_282_29.jpg"/> </div><br>
# 2. 实现 Singleton
[单例模式](设计模式.md)
# 3. 数组中重复的数字
[NowCoder](https://www.nowcoder.com/practice/623a5ac0ea5b4e5f95552655361ae0a8?tpId=13&tqId=11203&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
@ -115,24 +98,13 @@ Output:
## 解题思路
要求复杂度为 O(N) + O(1),也就是时间复杂度 O(N),空间复杂度 O(1)。因此不能使用排序的方法,也不能使用额外的标记数组。牛客网讨论区这一题的首票答案使用 nums[i] + length 来将元素标记,这么做会有加法溢出问题。
要求是时间复杂度 O(N),空间复杂度 O(1)。因此不能使用排序的方法,也不能使用额外的标记数组。
这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上。
对于这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解
以 (2, 3, 1, 0, 2, 5) 为例:
以 (2, 3, 1, 0, 2, 5) 为例,遍历到位置 4 时,该位置上的数为 2但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复
```text
position-0 : (2,3,1,0,2,5) // 2 <-> 1
(1,3,2,0,2,5) // 1 <-> 3
(3,1,2,0,2,5) // 3 <-> 0
(0,1,2,3,2,5) // already in position
position-1 : (0,1,2,3,2,5) // already in position
position-2 : (0,1,2,3,2,5) // already in position
position-3 : (0,1,2,3,2,5) // already in position
position-4 : (0,1,2,3,2,5) // nums[i] == nums[nums[i]], exit
```
遍历到位置 4 时,该位置上的数为 2但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复。
<div align="center"> <img src="pics/_u6570_u7EC4_u4E2D_u91CD_u590D_1548260392361.gif" width="250px"> </div><br>
```java
public boolean duplicate(int[] nums, int length, int[] duplication) {
@ -163,7 +135,7 @@ private void swap(int[] nums, int i, int j) {
## 题目描述
一个二维数组,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数
给定一个二维数组,每一行从左到右递增排序,从上到下也是递增排序。给定一个数,判断这个数是否在该二维数组中
```html
Consider the following matrix:
@ -181,13 +153,11 @@ Given target = 20, return false.
## 解题思路
从右上角开始查找。矩阵中的一个数,它左边的数都比它小,下边的数都比它大。因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来缩小查找区间
要求时间复杂度 O(M + N),空间复杂度 O(1)
复杂度O(M + N) + O(1)
该二维数组中的一个数,它左边的数都比它小,下边的数都比它大。因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来缩小查找区间,当前元素的查找区间为左下角的所有元素。
当前元素的查找区间为左下角的所有元素,例如元素 12 的查找区间如下:
<div align="center"> <img src="pics/f94389e9-55b1-4f49-9d37-00ed05900ae0.png" width="250"/> </div><br>
<div align="center"> <img src="pics/_u4E8C_u7EF4_u6570_u7EC4_u4E2D_.gif"/> </div><br>
```java
public boolean Find(int target, int[][] matrix) {
@ -218,10 +188,10 @@ public boolean Find(int target, int[][] matrix) {
```text
Input:
"We Are Happy"
"A B"
Output:
"We%20Are%20Happy"
"A%20B"
```
## 解题思路
@ -232,6 +202,8 @@ Output:
从后向前遍是为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容。
<div align="center"> <img src="pics/_u66FF_u6362_u7A7A_u683C.gif"/> </div><br>
```java
public String replaceSpace(StringBuffer str) {
int P1 = str.length() - 1;
@ -260,30 +232,16 @@ public String replaceSpace(StringBuffer str) {
## 题目描述
输入链表的第一个节点,从尾到头反过来打印出每个结点的值。
从尾到头反过来打印出每个结点的值。
<div align="center"> <img src="pics/d99dc9e2-197c-4085-813d-7195da1c6762.png" width="300"/> </div><br>
<div align="center"> <img src="pics/_u4ECE_u5C3E_u5230_u5934_u6253_1548293972480.gif" width="250px"> </div><br>
## 解题思路
### 使用栈
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
Stack<Integer> stack = new Stack<>();
while (listNode != null) {
stack.add(listNode.val);
listNode = listNode.next;
}
ArrayList<Integer> ret = new ArrayList<>();
while (!stack.isEmpty())
ret.add(stack.pop());
return ret;
}
```
### 使用递归
<div align="center"> <img src="pics/_u4ECE_u5C3E_u5230_u5934_u6253_1548296249372.gif" width="200px"> </div><br>
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> ret = new ArrayList<>();
@ -304,6 +262,8 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
- 头结点是在头插法中使用的一个额外节点,这个节点不存储值;
- 第一个节点就是链表的第一个真正存储值的节点。
<div align="center"> <img src="pics/_u4ECE_u5C3E_u5230_u5934_u6253_1548295232667.gif" width="300px"> </div><br>
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
// 头插法构建逆序链表
@ -325,16 +285,20 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
}
```
### 使用 Collections.reverse()
### 使用
<div align="center"> <img src="pics/_u4ECE_u5C3E_u5230_u5934_u6253_1548503461113.gif" width="500px"> </div><br>
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> ret = new ArrayList<>();
Stack<Integer> stack = new Stack<>();
while (listNode != null) {
ret.add(listNode.val);
stack.add(listNode.val);
listNode = listNode.next;
}
Collections.reverse(ret);
ArrayList<Integer> ret = new ArrayList<>();
while (!stack.isEmpty())
ret.add(stack.pop());
return ret;
}
```
@ -352,12 +316,14 @@ preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
```
<div align="center"> <img src="pics/8a4c6ad4-a816-47d1-b93f-7ca4f78ab67a.png" width="250"/> </div><br>
<div align="center"> <img src="pics/_u91CD_u5EFA_u4E8C_u53C9_u6811-1.gif" width="200"/> </div><br>
## 解题思路
前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序遍历结果,右部分为树的右子树中序遍历的结果。
<div align="center"> <img src="pics/_u91CD_u5EFA_u4E8C_u53C9_u6811-21548502782193.gif"/> </div><br>
```java
// 缓存中序遍历数组每个值对应的索引
private Map<Integer, Integer> indexForInOrders = new HashMap<>();
@ -406,11 +372,11 @@ public class TreeLinkNode {
① 如果一个节点的右子树不为空,那么该节点的下一个节点是右子树的最左节点;
<div align="center"> <img src="pics/cb0ed469-27ab-471b-a830-648b279103c8.png" width="250"/> </div><br>
<div align="center"> <img src="pics/_u4E8C_u53C9_u6811_u7684_u4E0B_.gif" width="250"/> </div><br>
② 否则,向上找第一个左链接指向的树包含该节点的祖先节点。
<div align="center"> <img src="pics/e143f6da-d114-4ba4-8712-f65299047fa2.png" width="250"/> </div><br>
<div align="center"> <img src="pics/_u4E8C_u53C9_u6811_u7684_u4E0B_1548504426508.gif" width="250"/> </div><br>
```java
public TreeLinkNode GetNext(TreeLinkNode pNode) {
@ -443,7 +409,8 @@ public TreeLinkNode GetNext(TreeLinkNode pNode) {
in 栈用来处理入栈push操作out 栈用来处理出栈pop操作。一个元素进入 in 栈之后,出栈的顺序被反转。当元素要出栈时,需要先进入 out 栈,此时元素出栈顺序再一次被反转,因此出栈顺序就和最开始入栈顺序是相同的,先进入的元素先退出,这就是队列的顺序。
<div align="center"> <img src="pics/5acf7550-86c5-4c5b-b912-8ce70ef9c34e.png" width="400"/> </div><br>
<div align="center"> <img src="pics/_u7528_u4E24_u4E2A_u6808_u5B9E_.gif" width="500"/> </div><br>
```java
Stack<Integer> in = new Stack<Integer>();
@ -479,7 +446,8 @@ public int pop() throws Exception {
如果使用递归求解,会重复计算一些子问题。例如,计算 f(10) 需要计算 f(9) 和 f(8),计算 f(9) 需要计算 f(8) 和 f(7),可以看到 f(8) 被重复计算了。
<div align="center"> <img src="pics/faecea49-9974-40db-9821-c8636137df61.jpg" width="300"/> </div><br>
<div align="center"> <img src="pics/_u6590_u6CE2_u90A3_u5951_u6570_u5217.gif" width="400"/> </div><br>
递归是将一个问题划分成多个子问题求解,动态规划也是如此,但是动态规划会把子问题的解缓存起来,从而避免重复求解子问题。

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、跨站脚本攻击](#一跨站脚本攻击)
* [二、跨站请求伪造](#二跨站请求伪造)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、事务](#一事务)
* [概念](#概念)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、构建工具的作用](#一构建工具的作用)
* [二、Java 主流构建工具](#二java-主流构建工具)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、概述](#一概述)
* [二、匹配单个字符](#二匹配单个字符)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、消息模型](#一消息模型)
* [点对点](#点对点)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、前言](#一前言)
* [二、算法分析](#二算法分析)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、性能](#一性能)
* [二、伸缩性](#二伸缩性)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、缓存特征](#一缓存特征)
* [二、LRU](#二lru)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、概述](#一概述)
* [基本特征](#基本特征)
@ -47,7 +47,7 @@
并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令。
并行需要硬件支持,如多流水线、多核处理器或分布式计算系统。
并行需要硬件支持,如多流水线、多核处理器或分布式计算系统。
操作系统通过引入进程和线程,使得程序能够并发运行。
@ -67,7 +67,7 @@
多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。
虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间和物理内存使用页进行交换,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。
虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间的页被映射到物理内存,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。
### 4. 异步

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、概述](#一概述)
* [网络的网络](#网络的网络)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、概述](#一概述)
* [二、创建型](#二创建型)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、负载均衡](#一负载均衡)
* [负载均衡算法](#负载均衡算法)

View File

@ -1,4 +1,4 @@
[🎉 面试进阶专栏限时优惠](https://xiaozhuanlan.com/CyC2018)
[🍉 点击订阅面试进阶专栏 ](https://xiaozhuanlan.com/CyC2018)
<!-- GFM-TOC -->
* [一、三大特性](#一三大特性)
* [封装](#封装)

BIN
docs/pics/1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB