Skip to content

Commit

Permalink
update toc
Browse files Browse the repository at this point in the history
  • Loading branch information
rbmonster committed May 4, 2022
1 parent 24c4a6f commit ed9baa6
Show file tree
Hide file tree
Showing 17 changed files with 654 additions and 200 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@

## 系统设计
### 设计思想及概念
- [设计及架构思想](/src/main/java/com/toc/SYSTEM-DESIGN.md)
- [设计及架构思想](/src/main/java/com/toc/SYSTEM_DESIGN.md)
- [设计模式](/src/main/java/com/toc/CODEDESIGN_BOOK.md)
- [分布式基本概念](/src/main/java/com/toc/DISTRIBUTED-SYSTEM.md)
- [分布式基本概念](/src/main/java/com/toc/DISTRIBUTED_SYSTEM.md)
- [领域驱动设计(DDD)](/src/main/java/com/toc/DDD.md)

### 设计案例
- [Java接口设计](/src/main/java/com/toc/INTERFACE_DESIGN.md)
Expand Down Expand Up @@ -115,6 +116,7 @@
| --- | --- |
| [fucking-algorithm](https://github.com/labuladong/fucking-algorithm) | labuladong刷算法套路,提供算法题的工具方法思想 |
| [leetcode-master](https://github.com/youngyangyang04/leetcode-master) | 代码随想录LeetCode 刷题攻略:配思维导图 |
| [LogicStack-LeetCode](https://github.com/SharingSource/LogicStack-LeetCode) | 「宫水三叶的刷题日记」刷穿 LeetCode 系列文章源码 |


系统设计及大数据:
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/com/bigdata/demo/SparkDemo.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.bigdata.demo;

import org.apache.commons.lang.CharSet;
import org.apache.spark.SparkConf;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/book/CODEDESIGN_BOOK.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# head first 设计模式
## 设计原则
## 设计原则
- 多用组合少用继承。
- 找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起。
- 针对接口编程,而不是针对实现编程。
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/design/DDD.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# DDD 领域驱动
# 领域驱动设计(Domain Driven Design,DDD)

基本元素:分层架构、实体、值对象、服务、模块、聚合、工厂、资源库

Expand Down
15 changes: 0 additions & 15 deletions src/main/java/com/design/SYSTEM_DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,3 @@ BFF 解决了什么问题?\

## 相关资料
[微服务拆分方法论](https://blog.csdn.net/no_game_no_life_/article/details/103390169)

# 中间件设计资料
![image](https://github.com/rbmonster/file-storage/blob/main/learning-note/design/systemdesign/disk-memory.png)

通常在大部分组件设计时,往往会选择一种主要介质来存储、另一种介质作为辅助使用。就拿 redis 来说,它主要采用内存存储数据,磁盘用来做辅助的持久化。拿 RabbitMQ 举例,它也是主要采用内存存储消息,但也支持将消息持久化到磁盘。而 RocketMQ、Kafka、Pulsar 这种,则是数据主要存储在磁盘,通过内存来主力提升系统的性能。关系型数据库例如 mysql 这种组件也是主要采用磁盘组织数据,合理利用内存提升性能。

针对采用内存存储数据的方案而言,难点一方面在于如何在不降低访问效率的情况下,充分利用有限的内存空间来存储尽可能多的数据,这个过程中少不了对数据结构的选型、优化;另一方面在于如何保证数据尽可能少的丢失,我们可以看到针对此问题的解决方案通常是快照+广泛意义的 wal 文件来解决。此类典型的代表就是 redis 啦。

针对采用磁盘存储数据的方案而言,难点一方面在于如何根据系统所要解决的特点场景进行合理的对磁盘布局。读多写少情况下采用 b+树方式存储数据;写多读少情况下采用 lsm tree 这类方案处理。另一方面在于如何尽可能减少对磁盘的频繁访问,一些做法是采用 mmap 进行内存映射,提升读性能;还有一些则是采用缓存机制缓存频繁访问的数据。还有一些则是采用巧妙的数据结构布局,充分利用磁盘预读特性保证系统性能。

**总的来说,针对写磁盘的优化,要不采用顺序写提升性能、要不采用异步写磁盘提升性能(异步写磁盘时需要结合 wal 保证数据的持久化,事实上 wal 也主要采用顺序写的特性);针对读磁盘的优化,一方面是缓存、另一方面是 mmap 内存映射加速读。**

上述这些存储方案上权衡的选择在 kafka、RocketMQ、Pulsar 中都可以看到。其实抛开消息队列而言,这些存储方案的选择上无论是关系型数据库还是 kv 型组件都是通用的。

[消息队列背后的设计思想](https://mp.weixin.qq.com/s/k8sA6XPrp80JiNbuwKaVfg)
74 changes: 69 additions & 5 deletions src/main/java/com/learning/algorithm/ALGORITHM.md
Original file line number Diff line number Diff line change
Expand Up @@ -1913,16 +1913,62 @@ class UnionFindSet {


## 二进制
计算1的个数

常用操作:

位运算与运算转换: \
[Pow(x, n)](https://leetcode-cn.com/problems/powx-n/) :快速幂
**判断负数**,快速的判断又避免精度溢出问题
```
private static void assertNumberMinus() {
int num1 = 1231;
int num2 = -12;
System.out.println("(1231 ^ -12) < 0 :" + ((num1 ^ num2) < 0));
}
```

**数字字符处理操作**: 统一转小写、统一转大写、大小写交换
```
统一转小写
('A' | ' ') = 'a';
('a' | ' ') = 'a';
统一转大写
('b' & '_') = 'B'
('B' & '_') = 'B'
大小写交换
('d' ^ ' ') = 'D'
('D' ^ ' ') = 'd'
```

**消除数字 n 的⼆进制表⽰中的最后⼀个1**`n&(n-1)`
- 计算一个数字转二进制后1的个数
- 判断一个数是否为2的指数
```
private static void countBit() {
int res = 0;
int num = 1002930;
int n = num;
while (n != 0) {
n = n & (n - 1);
res++;
}
System.out.println("num:" + num + ",count one number:" + res);
}
private static boolean isPowerOfTwo(int n) {
if (n <= 0) return false;
return (n & (n - 1)) == 0;
}
```


- [位1的个数](https://leetcode-cn.com/problems/number-of-1-bits/)
- [Pow(x, n)](https://leetcode-cn.com/problems/powx-n/) :快速幂,位运算与运算转换
- [剑指 Offer 56 - I. 数组中数字出现的次数](https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/)
## KMP
[实现 strStr()](https://leetcode-cn.com/problems/implement-strstr/)

## 常用操作
## 其他
### 前缀和
前缀和是一种重要的预处理,能大大降低查询的时间复杂度。两个位置的前缀和差值,能快速确定这段区间的`sumup`
> 相关关键词:**连续子数组**
Expand Down Expand Up @@ -1960,4 +2006,22 @@ class Solution {
return res;
}
}
```
```

### 约瑟夫环问题
**找出游戏的获胜者**该题为例:

我们第一轮会删掉第`k`个人,问题就变为对`n−1`个人进行这个游戏。\
假设我们知道`f(n−1,k)`最终剩下的人的编号,
由于我们删了第`k`个人,`n-1`个人的游戏是从原来第`k+1`个人开始的,\
**也就是说原来的编号和新的编号有一个偏差k**\
以坐标从0到`n-1`来看的话(去掉1的偏差减少计算量,最终加一次1即可),有公式:
`f(n,k) = (f(n - 1, k) + k) % n`

当只剩一个人时,他必然活下来,
`f(1,k) = 0`
我们从`f(1,k)`推出`f(2,k)`一直到`f(n,k)`即可。


相关问题:
- [找出游戏的获胜者](https://leetcode-cn.com/problems/find-the-winner-of-the-circular-game/)
98 changes: 98 additions & 0 deletions src/main/java/com/learning/algorithm/BitOperation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.learning.algorithm;


public class BitOperation {

public static void main(String[] args) {
toLowerCase();
toUpperCase();
exchangeCase();
assertNumberMinus();
exchangeNum();
countBit();
isPowerOfTwo(16);
}


/**
* 统一转小写
* ('A' | ' ') = 'a';
* ('a' | ' ') = 'a';
*/
private static void toLowerCase() {
char ch1 = 'c';
char ch2 = 'C';
System.out.println("('c'|' ') == 'c' :" + ((ch1 | ' ') == 'c'));
System.out.println("('C'|' ') == 'c' :" + ((ch2 | ' ') == 'c'));
}

/**
* 统一转大写
* ('b' & '_') = 'B'
* ('B' & '_') = 'B'
*/
private static void toUpperCase() {
char ch1 = 'c';
char ch2 = 'C';
System.out.println("('c' & '_') == 'C' :" + ((ch1 & '_') == 'C'));
System.out.println("('C' & '_') == 'C' :" + ((ch2 & '_') == 'C'));
}

/**
* 大小写交换
* ('d' ^ ' ') = 'D'
* ('D' ^ ' ') = 'd'
*/
private static void exchangeCase() {
char ch1 = 'c';
char ch2 = 'C';
System.out.println("('c' ^ ' ') == 'C' :" + ((ch1 ^ ' ') == 'C'));
System.out.println("('C' ^ ' ') == 'c' :" + ((ch2 ^ ' ') == 'c'));
}

/**
* 判断负数
*/
private static void assertNumberMinus() {
int num1 = 1231;
int num2 = -12;
System.out.println("(1231 ^ -12) < 0 :" + ((num1 ^ num2) < 0));
}

/**
* 数字交换
*/
private static void exchangeNum() {
int a = 12312;
int b = 22;
System.out.println("before num[a]:" + a + " num[b]:" + b);
a ^= b;
b ^= a;
a ^= b;
System.out.println("after num[a]:" + a + " num[b]:" + b);
}

/**
* 计算一个数二进制中1的个数
*/
private static void countBit() {
int res = 0;
int num = 1002930;
int n = num;
while (n != 0) {
n = n & (n - 1);
res++;
}
System.out.println("num:" + num + ",count one number:" + res);
}

/**
* 判断一个数是否为二的指数
* @param n
* @return
*/
private static boolean isPowerOfTwo(int n) {
if (n <= 0) return false;
return (n & (n - 1)) == 0;
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/other/OPERATING_SYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,20 @@

#### 读者-写者问题




# 中间件设计资料
![image](https://github.com/rbmonster/file-storage/blob/main/learning-note/design/systemdesign/disk-memory.png)

通常在大部分组件设计时,往往会选择一种主要介质来存储、另一种介质作为辅助使用。就拿 redis 来说,它主要采用内存存储数据,磁盘用来做辅助的持久化。拿 RabbitMQ 举例,它也是主要采用内存存储消息,但也支持将消息持久化到磁盘。而 RocketMQ、Kafka、Pulsar 这种,则是数据主要存储在磁盘,通过内存来主力提升系统的性能。关系型数据库例如 mysql 这种组件也是主要采用磁盘组织数据,合理利用内存提升性能。

针对采用内存存储数据的方案而言,难点一方面在于如何在不降低访问效率的情况下,充分利用有限的内存空间来存储尽可能多的数据,这个过程中少不了对数据结构的选型、优化;另一方面在于如何保证数据尽可能少的丢失,我们可以看到针对此问题的解决方案通常是快照+广泛意义的 wal 文件来解决。此类典型的代表就是 redis 啦。

针对采用磁盘存储数据的方案而言,难点一方面在于如何根据系统所要解决的特点场景进行合理的对磁盘布局。读多写少情况下采用 b+树方式存储数据;写多读少情况下采用 lsm tree 这类方案处理。另一方面在于如何尽可能减少对磁盘的频繁访问,一些做法是采用 mmap 进行内存映射,提升读性能;还有一些则是采用缓存机制缓存频繁访问的数据。还有一些则是采用巧妙的数据结构布局,充分利用磁盘预读特性保证系统性能。

**总的来说,针对写磁盘的优化,要不采用顺序写提升性能、要不采用异步写磁盘提升性能(异步写磁盘时需要结合 wal 保证数据的持久化,事实上 wal 也主要采用顺序写的特性);针对读磁盘的优化,一方面是缓存、另一方面是 mmap 内存映射加速读。**

上述这些存储方案上权衡的选择在 kafka、RocketMQ、Pulsar 中都可以看到。其实抛开消息队列而言,这些存储方案的选择上无论是关系型数据库还是 kv 型组件都是通用的。

[消息队列背后的设计思想](https://mp.weixin.qq.com/s/k8sA6XPrp80JiNbuwKaVfg)
77 changes: 71 additions & 6 deletions src/main/java/com/toc/ALGORITHM.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@
&emsp;<a href="#75">15. 并查集</a>
&emsp;<a href="#76">16. 二进制</a>
&emsp;<a href="#77">17. KMP</a>
&emsp;<a href="#78">18. 常用操作</a>
&emsp;<a href="#78">18. 其他</a>
&emsp;&emsp;<a href="#79">18.1. 前缀和</a>
&emsp;&emsp;<a href="#80">18.2. 求余数常见操作</a>
&emsp;&emsp;<a href="#81">18.3. Kanade 算法</a>
&emsp;&emsp;<a href="#82">18.4. 约瑟夫环问题</a>
# <a name="0">算法</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>

## <a name="1">链表</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>
Expand Down Expand Up @@ -1997,16 +1998,62 @@ class UnionFindSet {


## <a name="76">二进制</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>
计算1的个数

常用操作:

位运算与运算转换: \
[Pow(x, n)](https://leetcode-cn.com/problems/powx-n/) :快速幂
**判断负数**,快速的判断又避免精度溢出问题
```
private static void assertNumberMinus() {
int num1 = 1231;
int num2 = -12;
System.out.println("(1231 ^ -12) < 0 :" + ((num1 ^ num2) < 0));
}
```

**数字字符处理操作**: 统一转小写、统一转大写、大小写交换
```
统一转小写
('A' | ' ') = 'a';
('a' | ' ') = 'a';
统一转大写
('b' & '_') = 'B'
('B' & '_') = 'B'
大小写交换
('d' ^ ' ') = 'D'
('D' ^ ' ') = 'd'
```

**消除数字 n 的⼆进制表⽰中的最后⼀个1**`n&(n-1)`
- 计算一个数字转二进制后1的个数
- 判断一个数是否为2的指数
```
private static void countBit() {
int res = 0;
int num = 1002930;
int n = num;
while (n != 0) {
n = n & (n - 1);
res++;
}
System.out.println("num:" + num + ",count one number:" + res);
}
private static boolean isPowerOfTwo(int n) {
if (n <= 0) return false;
return (n & (n - 1)) == 0;
}
```


- [位1的个数](https://leetcode-cn.com/problems/number-of-1-bits/)
- [Pow(x, n)](https://leetcode-cn.com/problems/powx-n/) :快速幂,位运算与运算转换
- [剑指 Offer 56 - I. 数组中数字出现的次数](https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/)
## <a name="77">KMP</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>
[实现 strStr()](https://leetcode-cn.com/problems/implement-strstr/)

## <a name="78">常用操作</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>
## <a name="78">其他</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>
### <a name="79">前缀和</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>
前缀和是一种重要的预处理,能大大降低查询的时间复杂度。两个位置的前缀和差值,能快速确定这段区间的`sumup`
> 相关关键词:**连续子数组**
Expand Down Expand Up @@ -2044,4 +2091,22 @@ class Solution {
return res;
}
}
```
```

### <a name="82">约瑟夫环问题</a><a style="float:right;text-decoration:none;" href="#index">[Top]</a>
**找出游戏的获胜者**该题为例:

我们第一轮会删掉第`k`个人,问题就变为对`n−1`个人进行这个游戏。\
假设我们知道`f(n−1,k)`最终剩下的人的编号,
由于我们删了第`k`个人,`n-1`个人的游戏是从原来第`k+1`个人开始的,\
**也就是说原来的编号和新的编号有一个偏差k**\
以坐标从0到`n-1`来看的话(去掉1的偏差减少计算量,最终加一次1即可),有公式:
`f(n,k) = (f(n - 1, k) + k) % n`

当只剩一个人时,他必然活下来,
`f(1,k) = 0`
我们从`f(1,k)`推出`f(2,k)`一直到`f(n,k)`即可。


相关问题:
- [找出游戏的获胜者](https://leetcode-cn.com/problems/find-the-winner-of-the-circular-game/)
Loading

0 comments on commit ed9baa6

Please sign in to comment.