Skip to content

Commit 961b6ea

Browse files
feet: 编程题增加分类
1 parent b3260bb commit 961b6ea

13 files changed

+1055
-68
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ _book/
3939
.DS_Store
4040
./docs/.vuepress/dist
4141
/dist/
42+
/temp/

docs/.vuepress/config.js

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -166,29 +166,46 @@ module.exports = {
166166
},
167167
],
168168
'/jsCode/': [
169-
['/jsCode/', '手写代码系列'],
170-
['/jsCode/防抖', '手写一个防抖'],
171-
['/jsCode/节流', '手写一个节流'],
172-
['/jsCode/浅比较和深比较', '浅比较和深比较'],
173-
['/jsCode/浅拷贝和深拷贝', '浅拷贝和深拷贝'],
174-
['/jsCode/数组乱序', '数组乱序'],
175-
['/jsCode/函数柯里化', '函数柯里化'],
176-
['/jsCode/实现一个Promise', '实现一个Promise'],
177-
['/jsCode/实现一个new', '实现一个new'],
178-
['/jsCode/实现instanceof', '实现instanceof'],
179-
['/jsCode/实现flat', '实现flat'],
180-
['/jsCode/手写继承', '手写继承'],
181-
['/jsCode/实现一个async函数', '实现一个async函数'],
182-
['/jsCode/实现一个iterator', '实现一个iterator'],
183-
['/jsCode/setTimeout实现setInterval', 'setTimeout实现setInterval'],
184-
['/jsCode/限制并发请求', '限制并发请求'],
185-
['/jsCode/实现一个repeat方法', '实现一个repeat方法'],
186-
['/jsCode/简单实现一个Vue的双向绑定', '简单实现一个Vue的双向绑定'],
187-
['/jsCode/实现一个vue自定义指令-懒加载', '实现一个vue自定义指令-懒加载'],
188-
['/jsCode/实现一个轮播图', '实现一个轮播图'],
189-
['/jsCode/放大镜效果', '放大镜效果'],
190-
['/jsCode/LazyMan', '实现一个LazyMan'],
191-
['/jsCode/发布-订阅模式的实现', '发布-订阅模式的实现'],
169+
{
170+
title: 'API 实现',
171+
collapsable: true,
172+
children: [
173+
['/jsCode/实现一个Promise', '实现一个Promise'],
174+
['/jsCode/实现一个new', '实现一个new'],
175+
['/jsCode/实现instanceof', '实现instanceof'],
176+
['/jsCode/实现flat', '实现flat'],
177+
['/jsCode/手写继承', '手写继承'],
178+
['/jsCode/实现一个async函数', '实现一个async函数'],
179+
['/jsCode/实现一个iterator', '实现一个iterator'],
180+
['/jsCode/setTimeout实现setInterval', 'setTimeout实现setInterval'],
181+
['/jsCode/发布-订阅模式的实现', '实现一个 EventEmitter'],
182+
],
183+
title: '功能函数实现',
184+
collapsable: true,
185+
children: [
186+
['/jsCode/防抖', '手写一个防抖'],
187+
['/jsCode/节流', '手写一个节流'],
188+
['/jsCode/浅比较和深比较', '浅比较和深比较'],
189+
['/jsCode/浅拷贝和深拷贝', '浅拷贝和深拷贝'],
190+
['/jsCode/数组乱序', '数组乱序'],
191+
['/jsCode/函数柯里化', '函数柯里化'],
192+
],
193+
title: 'Promise 异步相关',
194+
collapsable: true,
195+
children: [
196+
['/jsCode/限制并发请求', '限制并发请求'],
197+
['/jsCode/实现一个repeat方法', '实现一个repeat方法'],
198+
['/jsCode/LazyMan', '实现一个LazyMan'],
199+
],
200+
title: '功能实现',
201+
collapsable: true,
202+
children: [
203+
['/jsCode/简单实现一个Vue的双向绑定', '简单实现一个Vue的双向绑定'],
204+
['/jsCode/实现一个vue自定义指令-懒加载', '实现一个vue自定义指令-懒加载'],
205+
['/jsCode/实现一个轮播图', '实现一个轮播图'],
206+
['/jsCode/放大镜效果', '放大镜效果'],
207+
],
208+
},
192209
],
193210
'/interview/': [
194211
['/interview/', '前端相关'],
@@ -255,7 +272,7 @@ module.exports = {
255272
],
256273
},
257274
{
258-
title: '笔试题',
275+
title: '代码输出题',
259276
collapsable: true,
260277
children: [
261278
// ['/interview/笔试题/1', '笔试题1'],
@@ -264,10 +281,10 @@ module.exports = {
264281
// ['/interview/笔试题/4', '笔试题4'],
265282
// ['/interview/笔试题/5', '笔试题5'],
266283
// ['/interview/笔试题/6', '笔试题6'],
267-
['/interview/笔试题/3', '笔试题1'],
268-
['/interview/笔试题/4', '笔试题2'],
269-
['/interview/笔试题/5', '笔试题3'],
270-
['/interview/笔试题/6', '笔试题4'],
284+
['/interview/笔试题/3', '代码输出题1'],
285+
['/interview/笔试题/4', '代码输出题2'],
286+
['/interview/笔试题/5', '代码输出题3'],
287+
['/interview/笔试题/6', '代码输出题4'],
271288
],
272289
},
273290
// {

docs/algorithm/其他/快速排序.md

Whitespace-only changes.

docs/algorithm/数学/计算质数.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,38 @@
22

33
## 解题思路
44

5-
质数:指在大于1的自然数中,除了1和它本身不再有其他因数的自然数。质数又称素数。
5+
质数:指在大于 1 的自然数中,除了 1 和它本身不再有其他因数的自然数。质数又称素数。
66

77
### 厄拉多塞筛法
8-
先将2-n的个数放入表中,然后在2的上面画一个圆圈,然后划去2的其他倍数,第一个既未画圈又没有划去的数是3,将它画圈,再划去3的其他倍数;
9-
现在即未画圈又没有划去的数是5,将它画圈并划去5的其他倍数......依次类推,一直到所有小于或等于N的各数都画了圈或者划去为止。这时,表中画了圈的以及未划去的那些数正好就是小于N的素数。
108

9+
先将 2-n 的个数放入表中,然后在 2 的上面画一个圆圈,然后划去 2 的其他倍数,第一个既未画圈又没有划去的数是 3,将它画圈,再划去 3 的其他倍数;
10+
现在即未画圈又没有划去的数是 5,将它画圈并划去 5 的其他倍数......依次类推,一直到所有小于或等于 N 的各数都画了圈或者划去为止。这时,表中画了圈的以及未划去的那些数正好就是小于 N 的素数。
1111

1212
![img](https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1589090399702.gif)
1313

14-
每计算一个数,都要把它的倍数去掉。到了n,数一下留下了几个数。
14+
每计算一个数,都要把它的倍数去掉。到了 n,数一下留下了几个数。
1515

1616
## 解题方法
17+
1718
```js
1819
/**
1920
* @param {number} n
2021
* @return {number}
2122
*/
2223
var countPrimes = function(n) {
23-
let count = 0;
24-
signs = new Array(n + 1);
25-
for(let i = 2; i < n; i++) {
26-
if(!signs[i]) {
27-
count++;
28-
for(let j = 2 * i; j < n; j+=i) {
29-
signs[j] = true;
24+
// isPrime[i] 表示数 i 是不是质数,如果是质数则为 1,否则为 0
25+
let isPrimes = new Array(n).fill(1);
26+
let ans = 0;
27+
for (let i = 2; i < n; i++) {
28+
if (isPrimes[i]) {
29+
ans += 1;
30+
// 从小到大遍历每个数,如果这个数为质数,则将其所有的倍数都标记为合数(除了该质数本身)即 00
31+
// 这样在运行结束的时候我们即能知道质数的个数。
32+
for (let j = i * i; j < n; j += i) {
33+
isPrimes[j] = 0;
3034
}
3135
}
3236
}
33-
return count;
37+
return ans;
3438
};
35-
```
39+
```
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
303. 区域和检索 - 数组不可变
2+
3+
使用前缀和,提高检索速度,时间复杂度为 O(1).
4+
5+
```js
6+
/**
7+
* @param {number[]} nums
8+
*/
9+
var NumArray = function(nums) {
10+
let n = nums.length;
11+
this.sums = new Array(n + 1).fill(0);
12+
for (let i = 0; i < n; i++) {
13+
// sums[i]表示 nums 从下标 00 到下标 i-1i−1 的前缀和。
14+
this.sums[i + 1] = nums[i] + this.sums[i];
15+
}
16+
};
17+
18+
/**
19+
* @param {number} left
20+
* @param {number} right
21+
* @return {number}
22+
*/
23+
NumArray.prototype.sumRange = function(left, right) {
24+
return this.sums[right + 1] - this.sums[left];
25+
};
26+
```
27+
28+
前缀和主要适用的场景是原始数组不会被修改的情况下,频繁查询某个区间的累加和。
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 思路
2+
3+
二叉搜索树,中序遍历是升序的。重复的数字一定是连续的,可以转变为,求有序数组中的众数。

docs/jsCode/LazyMan.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22

33
```js
44
实现一个LazyMan,可以按照以下方式调用:
5-
LazyMan(Hank)输出:
5+
LazyMan("Hank")输出:
66
Hi! This is Hank!
77

8-
LazyMan(Hank).sleep(10).eat(dinner”)输出
8+
LazyMan("Hank").sleep(10).eat("dinner") 输出
99
Hi! This is Hank!
1010
//等待10秒..
1111
Wake up after 10
1212
Eat dinner~
1313

14-
LazyMan(Hank).eat(dinner).eat(supper”)输出
14+
LazyMan('Hank').eat('dinner').eat('supper') 输出
1515
Hi This is Hank!
1616
Eat dinner~
1717
Eat supper~
1818

19-
LazyMan(Hank).sleepFirst(5).eat(supper)输出
19+
LazyMan("Hank").sleepFirst(5).eat("supper")输出
2020
//等待5秒
2121
Wake up after 5
2222
Hi This is Hank!
@@ -51,7 +51,7 @@ class LazyMan {
5151
while (Date.now() - time < delay) {}
5252
// 为什么在setTimeout里返回this不行, 函数执行会先于setTimeout里面的函数执行
5353
setTimeout(() => {
54-
console.log(' sleep wake up after ' + ms);
54+
console.log('sleep wake up after ' + ms);
5555
}, 0);
5656

5757
return this;
@@ -133,7 +133,7 @@ class _LazyMan {
133133
});
134134
return this.next();
135135
}
136-
beforSleep(time) {
136+
beforeSleep(time) {
137137
// unshift插入到事件的第一个
138138
this.taskQueue.unshift(() => this.sleepPromise(time));
139139
return this.next();

docs/jsCode/README.md

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
1-
### 目录
2-
- [实现一个防抖](./防抖.md)
3-
- [手写一个节流](./节流.md)
4-
- [浅比较和深比较](./浅比较和深比较.md)
5-
- [浅拷贝和深拷贝](./浅拷贝和深拷贝.md)
6-
- [数组乱序](./数组乱序.md)
7-
- [函数柯里化](./函数柯里化.md)
8-
- [实现一个Promise](./实现一个Promise.md)
9-
- [实现一个new](./实现一个new.md)
10-
- [实现instanceof](./实现instanceof.md)
11-
- [手写继承](./手写继承.md)
12-
- [实现一个async函数](./实现一个async函数.md)
13-
- [实现一个iterator](./实现一个iterator.md)
14-
- [setTimeout实现setInterval](./setTimeout实现setInterval.md)
15-
- [限制并发请求](./限制并发请求.md)
16-
- [简单实现一个Vue的双向绑定](./简单实现一个Vue的双向绑定.md)
17-
- [实现一个vue自定义指令-懒加载](./实现一个vue自定义指令-懒加载.md)
18-
- [实现一个轮播图](./实现一个轮播图.md)
19-
- [实现一个放大镜效果](./放大镜效果.md)
1+
## 目录
2+
3+
通过题目来学习一些 javaScript 基础知识
4+
5+
### API 实现
6+
7+
- [实现一个 new](./实现一个new.md)
8+
- [实现 instanceof](./实现instanceof.md)
9+
- [实现一个 iterator](./实现一个iterator.md)
10+
- [setTimeout 实现 setInterval](./setTimeout实现setInterval.md)
11+
- [写 call,apply,bind](./手写call,apply,bind.md)
12+
- [实现一个 EventEmitter](./发布-订阅模式的实现.md)
13+
14+
### 功能函数实现
15+
16+
- [手写继承](./手写继承.md)
17+
- [实现一个防抖](./防抖.md)
18+
- [手写一个节流](./节流.md)
19+
- [浅比较和深比较](./浅比较和深比较.md)
20+
- [浅拷贝和深拷贝](./浅拷贝和深拷贝.md)
21+
- [数组乱序](./数组乱序.md)
22+
- [函数柯里化](./函数柯里化.md)
23+
24+
### 数据结构转换
25+
26+
### Promise 异步相关
27+
28+
- [实现一个 Promise](./实现一个Promise.md)
29+
- [实现一个 async 函数](./实现一个async函数.md)
30+
- [限制并发请求](./限制并发请求.md)
31+
- [实现一个 LazyMan](./LazyMan.md)
32+
- [koa 洋葱模型 compose](./洋葱模型compose)
33+
- [实现一个 repeat 方法](./实现一个repeat方法.md)
34+
35+
### 功能实现
36+
37+
- [简单实现一个 Vue 的双向绑定](./简单实现一个Vue的双向绑定.md)
38+
- [实现一个 vue 自定义指令-懒加载](./实现一个vue自定义指令-懒加载.md)
39+
- [实现一个轮播图](./实现一个轮播图.md)
40+
- [实现一个放大镜效果](./放大镜效果.md)

docs/jsCode/compose和pipe.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 参考
2+
3+
- [compose 函数和 pipe 函数](http://dennisgo.cn/Articles/JavaScript/ComposePipe.html)

docs/jsCode/一维数组转树形结构.md

Whitespace-only changes.

docs/jsCode/实现一个虚拟列表.md

Whitespace-only changes.

docs/jsCode/洋葱模型compose.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## koa 的洋葱模型
2+
3+
```js
4+
app.use((next) => {
5+
console.log(1);
6+
next();
7+
console.log(4);
8+
});
9+
app.use((next) => {
10+
console.log(2);
11+
next();
12+
console.log(5);
13+
});
14+
app.use((next) => {
15+
console.log(3);
16+
next();
17+
console.log(6);
18+
});
19+
app.compose();
20+
// 输出是123654;
21+
```
22+
23+
当程序运行到 next()的时候就会暂停当前程序,进入下一个中间件,处理完之后才会回过头来继续处理。
24+
25+
核心:中间件管理和 next 实现,其中 next 是巧妙的使用了 Promise 特性。洋葱模型,本质上是 Promise.resolve()的递归。
26+
27+
## 参考
28+
29+
- [Koa 洋葱模型原理分析](https://lq782655835.github.io/blogs/node/koa-compose-modal.html)
30+
- [Koa2 洋葱模型 —— compose 串联中间件的四种实现](https://segmentfault.com/a/1190000016707187)

0 commit comments

Comments
 (0)