You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
5.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<div style="color:#16b0ff;font-size:50px;font-weight: 900;text-shadow: 5px 5px 10px var(--theme-color);font-family: 'Comic Sans MS';">Open</div>
<span style="color:#16b0ff;font-size:20px;font-weight: 900;font-family: 'Comic Sans MS';">Introduction</span>:收纳开放性设计问题相关的知识总结!
[TOC]
# 开放性设计
## 求两个文件中的QQ交集
**问题**A文件有30亿个QQ号码B文件有40亿个QQ号码求A文件和B文件中QQ号码的交集内存大小限制为1GB。
### 方案一:直接暴力比较
最简单的方法是直接暴力比较双重循环比较。显然这种方法要比较的次数是30亿×40亿时间复杂度太大。
### 方案二利用hashmap
将B文件中的40亿个QQ号码放入Hash表中然后遍历B文件中的30亿个QQ号码准一判断是否已在Hash表中存在。
显然应该用哈希表优化查找速度使得时间复杂度大大降低只需要遍历上面一层即可。然而空间的占用还是太大了1GB的内存根本无法容纳40亿个QQ号。
### 方案三:分治切割文件
既然内存容纳不下那就想办法进行切割比如根据QQ号码的最后一位的值来切割A文件和B文件使文件变小。显然尾数为j的QQ号码只可能在Aj文件和Bj文件中只需要比较Aj和Bj文件即可。
| QQ号最后一位 | A文件的切割 | B文件的切割 |
| ------------ | ----------- | ----------- |
| 0 | A0 | B0 |
| 1 | A1 | B1 |
| 2 | A2 | B2 |
| 3 | A3 | B3 |
| ... | ... | ... |
通过切割的方法可以化大为小让内存容纳得下。需要强调的是仅仅以QQ号最后一位来划分那么每个小文件的数据量大约是原来文件的1/10, 可能还是偏大。所以可以考虑以QQ号的最后3位来划分那么每个小文件的数据量大约是原来大文件的1/1000甚至还可以更细地来进行划分。通过一定的规则进行分割把A文件和B文件中同类型数据划分到对应的小文件中解决了内存问题。
### 方案四利用bitmap
可以对hashmap进行优化采用bitmap这种数据结构可以顺利地同时解决时间问题和空间问题。
| bit | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
| ----- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1个unsigned char类型的数据可以标识0~7这8个整数的存在与否。以此类推
- 1个unsigned int类型数据可以标识0~31这322^5个整数的存在与否
- 2个unsigned int类型数据可以标识0~63这642^6个整数的存在与否
- 3个unsigned int类型数据可以标识0~127这1282^7个整数的存在与否
- 4个unsigned int类型数据可以标识0~255这2562^8个整数的存在与否
- ......
- 28个unsigned int类型数据可以标识0~2^32-1这43亿2^32个整数的存在与否
10位QQ号码的理论最大值为 2^32 - 1 ≈ 43 亿bit。
占用内存43亿bit≈5.37亿bytes≈52万KB≈512MB
显然可以推导出512MB大小足够标识所有QQ号码的存在与否请注意QQ号码的理论最大值为2^32 - 1大概是43亿左右。接下来的问题就很简单了
用512MB的unsigned int数组来记录B文件中QQ号码的存在与否形成一个bitmap。然后遍历A文件中的QQ看是否在bitmap中如果在那么该QQ号码就同时存在于A和B两个文件中。
https://mp.weixin.qq.com/s/Q_EvlN9LvkdA5M5EharBBA
## 40亿个QQ号码如何去重
文件中有40亿个QQ号码请设计算法对QQ号码去重相同的QQ号码仅保留一个内存限制1G。
https://mp.weixin.qq.com/s/YlLYDzncB6tqbffrg__13w
### 方法一:排序
### 方法二hashmap
### 方法三:文件切割
### 方法四bitmap
## 群聊消息已读未读功能设计
企业IM比如企业微信、钉钉里面的群消息的有个已读未读的功能发送者刚发出消息时当前群里其他群成员都是未读状态陆陆续续有人看了这个消息这时候消息的详情变成x人已读y人未读。每条消息对应一个唯一的`messageiduint64_t`,每个用户对应一个唯一的`useriduint64_t`,应该如何保存这个消息对应的已读未读详情呢?
### 简单粗暴方案
对于每一个messageid存当前`read_ids + unread_ids`当群成员A已读某一条消息时把A的userid从unread_ids移除写到read_ids上就好了客户端更新到messageid对应的详情列表就可以展示m人已读n人未读。
按照目前的设计每一条消息已读未读详情就要占用8B × 群成员数的内存如果一个活跃的200人大群每发一条消息已读未读就要1600B如果平均每天消息量是1k那每个这样的群每天就要1.6MB磁盘空间,对于客户端来说,特别是手机端,占用磁盘空间是用户不能接受的,又不能把工作消息删了,对于服务器端来说,用户群体如果特别大,那数据库存储这个成本也不小。
### bitmap方案
## 未支付订单超时关闭