Skip to content

Commit f14be78

Browse files
add:自动拉取题解&自动生成json
1 parent 5e32844 commit f14be78

File tree

366 files changed

+45181
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

366 files changed

+45181
-2
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
|---App.js 主逻辑都在这里
1616
```
1717

18-
## 构建
1918

19+
20+
## 构建
21+
- npm run auto 自动生成问题解答json
2022
- npm run build
2123
- 然后将 build 文件夹的内容添加到扩展中即可,具体方式见上面的`功能介绍`
2224

package-lock.json

Lines changed: 14644 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
"start": "react-scripts start",
1616
"build": "react-scripts build",
1717
"test": "react-scripts test",
18-
"eject": "react-scripts eject"
18+
"eject": "react-scripts eject",
19+
"auto": "node scripts/curl-leetcode.js && node scripts/generate-leetcode.js"
20+
1921
},
2022
"eslintConfig": {
2123
"extends": "react-app"
@@ -31,5 +33,10 @@
3133
"last 1 firefox version",
3234
"last 1 safari version"
3335
]
36+
},
37+
"devDependencies": {
38+
"cheerio": "^1.0.0-rc.3",
39+
"iconv-lite": "^0.5.1",
40+
"log4js": "^6.3.0"
3441
}
3542
}

scripts/LeetCodeProvider.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
2+
3+
const request = require('request')
4+
const Iconv = require('iconv-lite')
5+
const cheerio = require('cheerio')
6+
const Logger = require('./Logger')
7+
8+
9+
10+
class LeetCodeProvider {
11+
12+
13+
static getInstance() {
14+
return this.oInstance || (this.oInstance = new LeetCodeProvider)
15+
}
16+
17+
getProblemsTitle() {
18+
return new Promise((ok,unExpect) => {
19+
20+
Logger.success('正在获取问题列表...')
21+
22+
request({
23+
method:'GET',
24+
url:'https://github.com/azl397985856/leetcode/tree/master/problems',
25+
encoding:null},
26+
(error,response,body) => {
27+
if(error) {
28+
unExpect(Logger.error('获取问题列表失败',error) && error)
29+
} else {
30+
let aProblemTitles =[]
31+
let sHtml = Iconv.decode(body, 'utf-8').toString()
32+
cheerio.load(sHtml)('.js-navigation-item .content .js-navigation-open ').each((idx,ele)=> aProblemTitles.push(ele.attribs['title']) )
33+
Logger.success('获取问题列表成功')
34+
ok(aProblemTitles)
35+
}
36+
})
37+
38+
})
39+
}
40+
41+
getProblemDetail(problemNameWithExt) {
42+
return new Promise((ok, unExpect) => {
43+
44+
Logger.success('正在抓取问题:', problemNameWithExt)
45+
46+
request({
47+
method:'GET',
48+
url:`https://raw.githubusercontent.com/azl397985856/leetcode/master/problems/${problemNameWithExt}`,
49+
encoding:null
50+
},
51+
(error,response,body) => {
52+
if (error) {
53+
unExpect(Logger.error(`抓取问题 "${problemNameWithExt}" 失败`,error) && error)
54+
} else {
55+
let markdown = Iconv.decode(body, 'utf-8').toString()
56+
Logger.success(`抓取问题 "${problemNameWithExt}" 成功!`)
57+
ok(markdown)
58+
}
59+
60+
})
61+
})
62+
}
63+
64+
}
65+
66+
module.exports = LeetCodeProvider

scripts/Logger.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
const log4js = require("log4js");
3+
4+
const logger = log4js.getLogger()
5+
6+
logger.level = 'debug'
7+
8+
logger.category = 'LeetCode'
9+
10+
class Logger {
11+
12+
13+
14+
static success(...args) {
15+
logger.info(...args)
16+
}
17+
18+
static error(...args) {
19+
logger.error(...args)
20+
}
21+
22+
}
23+
24+
module.exports = Logger

scripts/constants.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
3+
4+
module.exports = {
5+
support_language: [
6+
'java',
7+
'python',
8+
'javascript'
9+
]
10+
}

scripts/curl-leetcode.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const LeetCodeProvider = require('./LeetCodeProvider')
2+
3+
const Logger = require('./Logger')
4+
5+
const Utils = require('./utils')
6+
7+
/**
8+
* 请求处理频率 ms
9+
*/
10+
const requestRate = 300
11+
12+
/**
13+
* 当前请求问题索引
14+
*/
15+
let requsetNumber = 0
16+
17+
18+
const getProblemDetail = (questionsName, requsetNumber) => {
19+
20+
const cachedFilesName = Utils.getDirsFileName('spider/row-markdown')
21+
22+
if ( cachedFilesName.includes(questionsName[requsetNumber]) ) {
23+
24+
Logger.success(`${questionsName[requsetNumber]}命中缓存, 跳过。。。`)
25+
26+
requsetNumber++
27+
28+
setTimeout(() => {
29+
30+
getProblemDetail(questionsName, requsetNumber)
31+
32+
}, requestRate)
33+
}
34+
else {
35+
36+
questionsName[requsetNumber] && LeetCodeProvider.getInstance().getProblemDetail(questionsName[requsetNumber]).then(markDown => {
37+
38+
Logger.success(`问题: "${questionsName[requsetNumber]}" | 结果: ${JSON.stringify(markDown)}`)
39+
40+
Utils.writeFileSync('spider/row-markdown/',questionsName[requsetNumber],markDown)
41+
42+
requsetNumber++
43+
}).catch(Logger.error).then(() => {
44+
45+
setTimeout(() => {
46+
47+
questionsName[requsetNumber] && getProblemDetail(questionsName, requsetNumber)
48+
49+
}, requestRate)
50+
})
51+
}
52+
53+
}
54+
55+
56+
LeetCodeProvider.getInstance().getProblemsTitle().then(questionsName => {
57+
58+
getProblemDetail(questionsName, requsetNumber)
59+
60+
})
61+
62+
63+
64+

scripts/generate-leetcode.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
const Utils = require('./utils')
2+
const Logger = require('./Logger')
3+
const { support_language } = require('./constants')
4+
5+
6+
7+
8+
const genertateLeetcodeToJson = () => {
9+
const rowMarkdowns = Utils.getDirsFileName('spider/row-markdown')
10+
11+
rowMarkdowns.forEach(filename => {
12+
13+
let languageResloved = []
14+
let markdown
15+
16+
try {
17+
18+
Logger.success(`开始读取${filename}`)
19+
20+
markdown = Utils.readFileSync(`spider/row-markdown/`,filename)
21+
22+
Logger.success(`读取${filename}完毕`)
23+
24+
}
25+
catch (error) {
26+
27+
Logger.error(`读取${filename}失败`,error)
28+
}
29+
30+
31+
/**
32+
* 此替换是为了解决正则匹配java时出现的问题
33+
*/
34+
35+
markdown = markdown.replace(/```javascript/g, '```js')
36+
37+
support_language.forEach(lang => {
38+
39+
markdown.replace(Utils.genRegByLang(lang), (noUseMatch, $1) => {
40+
41+
languageResloved.push({
42+
lang,
43+
code: $1
44+
})
45+
46+
})
47+
48+
49+
let oCustomStruct = {
50+
question: filename.slice(0,-3),
51+
companys: ['TODO'],
52+
tags: ['TODO'],
53+
reslove: languageResloved
54+
}
55+
56+
57+
58+
Logger.success(`开始生成 "${filename}"`)
59+
60+
Utils.writeFileSync('spider/yield-db-json',`${filename.slice(0,-3)}.json`, JSON.stringify(oCustomStruct, null, 2))
61+
62+
Logger.success(`生成 "${filename}" 完毕`)
63+
64+
})
65+
66+
67+
68+
69+
})
70+
71+
72+
}
73+
74+
genertateLeetcodeToJson()

scripts/utils.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const fs = require('fs')
2+
const { resolve : pathResolve } = require('path')
3+
4+
const { support_language } = require('./constants')
5+
6+
7+
class Utils {
8+
9+
10+
/**
11+
* 获取不同语言的正则表达式
12+
*
13+
* @static
14+
* @param {*} lang
15+
* @returns
16+
* @memberof Utils
17+
*/
18+
static genRegByLang(lang) {
19+
return new RegExp( `(?:\`\`\`${lang})((.|[\r\n])*?)(?:\`\`\`)`,'g')
20+
}
21+
22+
23+
static readFileSync(relativePath,filename) {
24+
return fs.readFileSync(pathResolve(__dirname, '../',relativePath,filename),{encoding:'utf8'})
25+
}
26+
27+
static getDirsFileName(dir) {
28+
return fs.readdirSync(pathResolve(__dirname, '../', dir), {encoding:'utf8'})
29+
}
30+
31+
32+
33+
static writeFileSync(dir,name,content) {
34+
fs.writeFileSync(pathResolve(__dirname, '../', dir ,name),content)
35+
}
36+
37+
38+
39+
}
40+
41+
42+
43+
44+
45+
46+
module.exports = Utils

spider/row-markdown/1.TwoSum.en.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
## Problem
2+
https://leetcode-cn.com/problems/two-sum
3+
4+
## Problem Description
5+
```
6+
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
7+
8+
You may assume that each input would have exactly one solution, and you may not use the same element twice.
9+
10+
Example:
11+
12+
Given nums = [2, 7, 11, 15], target = 9,
13+
14+
Because nums[0] + nums[1] = 2 + 7 = 9,
15+
return [0, 1].
16+
```
17+
18+
## Solution
19+
The easiest solution to come up with is Brute Force. We could write two for-loops to traverse every element, and find the target numbers that meet the requirement. However, the time complexity of this solution is O(N^2), while the space complexity is O(1). Apparently, we need to find a way to optimize this solution since the time complexity is too high. What we could do is to record the numbers we have traversed and the relevant index with a Map. Whenever we meet a new number during traversal, we go back to the Map and check whether the `diff` between this number and the target number appeared before. If it did, the problem has been solved and there's no need to continue.
20+
21+
## Key Points
22+
- Find the difference instead of the sum
23+
- Connect every number with its index through the help of Map
24+
- Less time by more space. Reduce the time complexity from O(N) to O(1)
25+
26+
## Code
27+
- Support Language: JS
28+
29+
```js
30+
/**
31+
* @param {number[]} nums
32+
* @param {number} target
33+
* @return {number[]}
34+
*/
35+
const twoSum = function (nums, target) {
36+
const map = new Map();
37+
for (let i = 0; i < nums.length; i++) {
38+
const diff = target - nums[i];
39+
if (map.has(diff)) {
40+
return [map.get(diff), i];
41+
}
42+
map.set(nums[i], i);
43+
}
44+
}
45+
```
46+
47+
***Complexity Anlysis***
48+
49+
- *Time Complexity*: O(N)
50+
- *Space Complexity*:O(N)

0 commit comments

Comments
 (0)