Skip to content

Commit ac9ccd1

Browse files
committed
feat: 测试用例中补充树和链表的数据结构以及转换逻辑,新增单元测试模块
1 parent 3dbb637 commit ac9ccd1

File tree

22 files changed

+3336
-378
lines changed

22 files changed

+3336
-378
lines changed

common/resources/store.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"today":"2182","today-question-info":{"enName":"stone-game-vi","title":"石子游戏 VI","detail":"<p>Alice 和 Bob 轮流玩一个游戏,Alice 先手。</p>\n\n<p>一堆石子里总共有 <code>n</code> 个石子,轮到某个玩家时,他可以 <strong>移出</strong> 一个石子并得到这个石子的价值。Alice 和 Bob 对石子价值有 <strong>不一样的的评判标准</strong> 。双方都知道对方的评判标准。</p>\n\n<p>给你两个长度为 <code>n</code> 的整数数组 <code>aliceValues</code> 和 <code>bobValues</code> 。<code>aliceValues[i]</code> 和 <code>bobValues[i]</code> 分别表示 Alice 和 Bob 认为第 <code>i</code> 个石子的价值。</p>\n\n<p>所有石子都被取完后,得分较高的人为胜者。如果两个玩家得分相同,那么为平局。两位玩家都会采用 <b>最优策略</b> 进行游戏。</p>\n\n<p>请你推断游戏的结果,用如下的方式表示:</p>\n\n<ul>\n\t<li>如果 Alice 赢,返回 <code>1</code> 。</li>\n\t<li>如果 Bob 赢,返回 <code>-1</code> 。</li>\n\t<li>如果游戏平局,返回 <code>0</code> 。</li>\n</ul>\n\n<p> </p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<b>输入:</b>aliceValues = [1,3], bobValues = [2,1]\n<b>输出:</b>1\n<strong>解释:</strong>\n如果 Alice 拿石子 1 (下标从 0开始),那么 Alice 可以得到 3 分。\nBob 只能选择石子 0 ,得到 2 分。\nAlice 获胜。\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<strong>输入:</strong>aliceValues = [1,2], bobValues = [3,1]\n<b>输出:</b>0\n<strong>解释:</strong>\nAlice 拿石子 0 , Bob 拿石子 1 ,他们得分都为 1 分。\n打平。\n</pre>\n\n<p><strong>示例 3:</strong></p>\n\n<pre>\n<b>输入:</b>aliceValues = [2,4,3], bobValues = [1,6,7]\n<b>输出:</b>-1\n<strong>解释:</strong>\n不管 Alice 怎么操作,Bob 都可以得到比 Alice 更高的得分。\n比方说,Alice 拿石子 1 ,Bob 拿石子 2 , Alice 拿石子 0 ,Alice 会得到 6 分而 Bob 得分为 7 分。\nBob 会获胜。\n</pre>\n\n<p> </p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>n == aliceValues.length == bobValues.length</code></li>\n\t<li><code>1 <= n <= 10<sup>5</sup></code></li>\n\t<li><code>1 <= aliceValues[i], bobValues[i] <= 100</code></li>\n</ul>\n","id":"1686","jsCode":"/**\n * @param {number[]} aliceValues\n * @param {number[]} bobValues\n * @return {number}\n */\nvar stoneGameVI = function(aliceValues, bobValues) {\n\n};","date":"2024-02-02"},"today-tag":"82","random-id":1314,"random-question-info":{"enName":"multiply-strings","title":"字符串相乘","detail":"<p>给定两个以字符串形式表示的非负整数&nbsp;<code>num1</code>&nbsp;和&nbsp;<code>num2</code>,返回&nbsp;<code>num1</code>&nbsp;和&nbsp;<code>num2</code>&nbsp;的乘积,它们的乘积也表示为字符串形式。</p>\n\n<p><strong>注意:</strong>不能使用任何内置的 BigInteger 库或直接将输入转换为整数。</p>\n\n<p>&nbsp;</p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong> num1 = \"2\", num2 = \"3\"\n<strong>输出:</strong> \"6\"</pre>\n\n<p><strong>示例&nbsp;2:</strong></p>\n\n<pre>\n<strong>输入:</strong> num1 = \"123\", num2 = \"456\"\n<strong>输出:</strong> \"56088\"</pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>1 &lt;= num1.length, num2.length &lt;= 200</code></li>\n\t<li><code>num1</code>&nbsp;和 <code>num2</code>&nbsp;只能由数字组成。</li>\n\t<li><code>num1</code>&nbsp;和 <code>num2</code>&nbsp;都不包含任何前导零,除了数字0本身。</li>\n</ul>\n","id":"43","jsCode":"/**\n * @param {string} num1\n * @param {string} num2\n * @return {string}\n */\nvar multiply = function(num1, num2) {\n\n};"},"specified-question-info":{"enName":"vvXgSW","title":"合并 K 个升序链表","detail":"<p>给定一个链表数组,每个链表都已经按升序排列。</p>\n\n<p>请将所有链表合并到一个升序链表中,返回合并后的链表。</p>\n\n<p>&nbsp;</p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong>lists = [[1,4,5],[1,3,4],[2,6]]\n<strong>输出:</strong>[1,1,2,3,4,4,5,6]\n<strong>解释:</strong>链表数组如下:\n[\n 1-&gt;4-&gt;5,\n 1-&gt;3-&gt;4,\n 2-&gt;6\n]\n将它们合并到一个有序链表中得到。\n1-&gt;1-&gt;2-&gt;3-&gt;4-&gt;4-&gt;5-&gt;6\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<strong>输入:</strong>lists = []\n<strong>输出:</strong>[]\n</pre>\n\n<p><strong>示例 3:</strong></p>\n\n<pre>\n<strong>输入:</strong>lists = [[]]\n<strong>输出:</strong>[]\n</pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>k == lists.length</code></li>\n\t<li><code>0 &lt;= k &lt;= 10^4</code></li>\n\t<li><code>0 &lt;= lists[i].length &lt;= 500</code></li>\n\t<li><code>-10^4 &lt;= lists[i][j] &lt;= 10^4</code></li>\n\t<li><code>lists[i]</code> 按 <strong>升序</strong> 排列</li>\n\t<li><code>lists[i].length</code> 的总和不超过 <code>10^4</code></li>\n</ul>\n\n<p>&nbsp;</p>\n\n<p><meta charset=\"UTF-8\" />注意:本题与主站 23&nbsp;题相同:&nbsp;<a href=\"https://leetcode-cn.com/problems/merge-k-sorted-lists/\">https://leetcode-cn.com/problems/merge-k-sorted-lists/</a></p>\n","id":"LCR 078","jsCode":"/**\n * Definition for singly-linked list.\n * function ListNode(val, next) {\n * this.val = (val===undefined ? 0 : val)\n * this.next = (next===undefined ? null : next)\n * }\n */\n/**\n * @param {ListNode[]} lists\n * @return {ListNode}\n */\nvar mergeKLists = function(lists) {\n\n};"}}
1+
{"today":"2182","today-question-info":{"enName":"stone-game-vii","title":"石子游戏 VII","detail":"<p>石子游戏中,爱丽丝和鲍勃轮流进行自己的回合,<strong>爱丽丝先开始</strong> 。</p>\n\n<p>有 <code>n</code> 块石子排成一排。每个玩家的回合中,可以从行中 <strong>移除</strong> 最左边的石头或最右边的石头,并获得与该行中剩余石头值之 <strong>和</strong> 相等的得分。当没有石头可移除时,得分较高者获胜。</p>\n\n<p>鲍勃发现他总是输掉游戏(可怜的鲍勃,他总是输),所以他决定尽力 <strong>减小得分的差值</strong> 。爱丽丝的目标是最大限度地 <strong>扩大得分的差值</strong> 。</p>\n\n<p>给你一个整数数组 <code>stones</code> ,其中 <code>stones[i]</code> 表示 <strong>从左边开始</strong> 的第 <code>i</code> 个石头的值,如果爱丽丝和鲍勃都 <strong>发挥出最佳水平</strong> ,请返回他们 <strong>得分的差值</strong> 。</p>\n\n<p> </p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong>stones = [5,3,1,4,2]\n<strong>输出:</strong>6\n<strong>解释:</strong>\n- 爱丽丝移除 2 ,得分 5 + 3 + 1 + 4 = 13 。游戏情况:爱丽丝 = 13 ,鲍勃 = 0 ,石子 = [5,3,1,4] 。\n- 鲍勃移除 5 ,得分 3 + 1 + 4 = 8 。游戏情况:爱丽丝 = 13 ,鲍勃 = 8 ,石子 = [3,1,4] 。\n- 爱丽丝移除 3 ,得分 1 + 4 = 5 。游戏情况:爱丽丝 = 18 ,鲍勃 = 8 ,石子 = [1,4] 。\n- 鲍勃移除 1 ,得分 4 。游戏情况:爱丽丝 = 18 ,鲍勃 = 12 ,石子 = [4] 。\n- 爱丽丝移除 4 ,得分 0 。游戏情况:爱丽丝 = 18 ,鲍勃 = 12 ,石子 = [] 。\n得分的差值 18 - 12 = 6 。\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<strong>输入:</strong>stones = [7,90,5,1,100,10,10,2]\n<strong>输出:</strong>122</pre>\n\n<p> </p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>n == stones.length</code></li>\n\t<li><code>2 <= n <= 1000</code></li>\n\t<li><code>1 <= stones[i] <= 1000</code></li>\n</ul>\n","id":"1690","jsCode":"/**\n * @param {number[]} stones\n * @return {number}\n */\nvar stoneGameVII = function(stones) {\n\n};","date":"2024-02-03"},"today-tag":"82","random-id":1314,"random-question-info":{"enName":"multiply-strings","title":"字符串相乘","detail":"<p>给定两个以字符串形式表示的非负整数&nbsp;<code>num1</code>&nbsp;和&nbsp;<code>num2</code>,返回&nbsp;<code>num1</code>&nbsp;和&nbsp;<code>num2</code>&nbsp;的乘积,它们的乘积也表示为字符串形式。</p>\n\n<p><strong>注意:</strong>不能使用任何内置的 BigInteger 库或直接将输入转换为整数。</p>\n\n<p>&nbsp;</p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong> num1 = \"2\", num2 = \"3\"\n<strong>输出:</strong> \"6\"</pre>\n\n<p><strong>示例&nbsp;2:</strong></p>\n\n<pre>\n<strong>输入:</strong> num1 = \"123\", num2 = \"456\"\n<strong>输出:</strong> \"56088\"</pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>1 &lt;= num1.length, num2.length &lt;= 200</code></li>\n\t<li><code>num1</code>&nbsp;和 <code>num2</code>&nbsp;只能由数字组成。</li>\n\t<li><code>num1</code>&nbsp;和 <code>num2</code>&nbsp;都不包含任何前导零,除了数字0本身。</li>\n</ul>\n","id":"43","jsCode":"/**\n * @param {string} num1\n * @param {string} num2\n * @return {string}\n */\nvar multiply = function(num1, num2) {\n\n};"},"specified-question-info":{"enName":"symmetric-tree","title":"对称二叉树","detail":"<p>给你一个二叉树的根节点 <code>root</code> , 检查它是否轴对称。</p>\n\n<p>&nbsp;</p>\n\n<p><strong>示例 1:</strong></p>\n<img alt=\"\" src=\"https://pic.leetcode.cn/1698026966-JDYPDU-image.png\" style=\"width: 354px; height: 291px;\" />\n<pre>\n<strong>输入:</strong>root = [1,2,2,3,4,4,3]\n<strong>输出:</strong>true\n</pre>\n\n<p><strong>示例 2:</strong></p>\n<img alt=\"\" src=\"https://pic.leetcode.cn/1698027008-nPFLbM-image.png\" style=\"width: 308px; height: 258px;\" />\n<pre>\n<strong>输入:</strong>root = [1,2,2,null,3,null,3]\n<strong>输出:</strong>false\n</pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li>树中节点数目在范围 <code>[1, 1000]</code> 内</li>\n\t<li><code>-100 &lt;= Node.val &lt;= 100</code></li>\n</ul>\n\n<p>&nbsp;</p>\n\n<p><strong>进阶:</strong>你可以运用递归和迭代两种方法解决这个问题吗?</p>\n","id":"101","jsCode":"/**\n * Definition for a binary tree node.\n * function TreeNode(val, left, right) {\n * this.val = (val===undefined ? 0 : val)\n * this.left = (left===undefined ? null : left)\n * this.right = (right===undefined ? null : right)\n * }\n */\n/**\n * @param {TreeNode} root\n * @return {boolean}\n */\nvar isSymmetric = function(root) {\n\n};"}}

common/structures/TreeNode.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
class TreeNode {
2+
constructor(val, left, right) {
3+
this.left = null;
4+
this.val = (val===undefined ? 0 : val)
5+
this.left = (left===undefined ? null : left)
6+
this.right = (right===undefined ? null : right)
7+
}
8+
parse(arr) {
9+
if(arr.length === 0) return null
10+
let root = new TreeNode(arr[0])
11+
let queue = [root]
12+
for(let i = 1; i < arr.length; i += 2)
13+
{
14+
let node = queue.shift()
15+
if(arr[i] !== null)
16+
{
17+
node.left = new TreeNode(arr[i])
18+
queue.push(node.left)
19+
}
20+
if(arr[i+1] !== null)
21+
{
22+
node.right = new TreeNode(arr[i+1])
23+
queue.push(node.right)
24+
}
25+
}
26+
return root
27+
}
28+
toArray(treeNode) {
29+
const result = [];
30+
if (!treeNode) {
31+
return result;
32+
}
33+
34+
const queue = [treeNode];
35+
36+
while (queue.length > 0) {
37+
const node = queue.shift();
38+
if (node) {
39+
result.push(node.val);
40+
queue.push(node.left);
41+
queue.push(node.right);
42+
} else {
43+
result.push(null);
44+
}
45+
}
46+
47+
while (result.length > 0 && result[result.length - 1] === null) {
48+
result.pop();
49+
}
50+
51+
return result;
52+
}
53+
}
54+
module.exports = {TreeNode}

common/utils/fulfillQuestion.js

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
const { removeDomTags } = require("./removeDomTags");
33
const {getTestCase} = require("./getTestCase");
44
const {getQuestionUrl} = require("./getQuestionUrl");
5+
// import {getQuestion} from "./getQuestion";
56
/**
67
* 填充模板文件
78
* @param questionPath

common/utils/getTestCase.js

+35-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
1-
/**
1+
const { ListNode, parse, toArray } = require("../structures/ListNode");
2+
3+
4+
/**
5+
* 获取test case 入参的数据类型
6+
* @param {string} jsCode leetcode的实例函数体
7+
* @param {string} type 类型,param入参,returns返回值
8+
* @returns {string[]}
9+
*/
10+
const getDataStructure = (jsCode, type = 'param') => {
11+
const regexMap = {
12+
param: /@param\s+{\s*([^}\s]+)\s*}/g,
13+
return: /@return\s+{\s*([^}\s]+)\s*}/g
14+
};
15+
const regex = regexMap[type];
16+
const paramTypes = [];
17+
let match;
18+
while ((match = regex.exec(jsCode)) !== null) {
19+
paramTypes.push(match[1]);
20+
}
21+
return paramTypes
22+
}
23+
24+
25+
26+
/**
227
* test case 需要从两个地方拿到内容
328
* 1.详情:拿到默认的几个用例
429
* 2.函数名:拿到函数名创建用例函数
530
* @param question
631
* @returns {string}
732
*/
833
function getTestCase(question){
9-
console.log(question)
1034
const detail = question.detail.replaceAll("`","");
1135
const cases = detail.match(/(<[a-zA-Z]+>)?[|:](<\/[a-zA-Z]+>)?.+\n/g)
1236
?.map(str=>`[${str?.replace(/(<[a-zA-Z]+>)?[|:]/gm,"")?.replace(/(<\/[a-zA-Z]+>)?/,"")?.replace("\n","")}]`)
@@ -15,8 +39,14 @@ function getTestCase(question){
1539
const functionName = question.jsCode?.match(/var.+=/g)?.[0]?.replace("var ","")?.replace(" =","");
1640
return `showLogs(
1741
${functionName},
18-
[${cases}],
19-
[${expires}]
42+
{
43+
data: [${cases}],
44+
structure: ${JSON.stringify(getDataStructure(question.jsCode))},
45+
},
46+
{
47+
data: [${expires}],
48+
structrue: ${JSON.stringify(getDataStructure(question.jsCode, 'return'))}
49+
}
2050
)`
2151
}
22-
module.exports = {getTestCase}
52+
module.exports = {getTestCase, getDataStructure}

common/utils/parseStructure.js

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
2+
const {parse, toArray} = require('../structures/ListNode')
3+
const {TreeNode} = require('../structures/TreeNode')
4+
/**
5+
*
6+
* @param {Array} params
7+
* @param {string[]} structs
8+
* @param {string} type
9+
*/
10+
const setDataStructure = (params, structs,type='cases') => {
11+
12+
const paramMap = (param) =>{
13+
14+
return {
15+
// 入参map
16+
cases: {
17+
ListNode:(param) => parse(param),
18+
'ListNode[]':(param) => param.map(res => parse(res)),
19+
TreeNode:(param) => {
20+
const node = new TreeNode(param);
21+
return node.parse(param)
22+
},
23+
default: param,
24+
25+
},
26+
// 返回值map
27+
return: {
28+
ListNode: (param) => toArray(param),
29+
'ListNode[]':(param) => param.map(res => toArray(res)),
30+
TreeNode:(param) => {
31+
const node = new TreeNode(param);
32+
return node.toArray(param)
33+
},
34+
default: param => param,
35+
36+
}
37+
}
38+
}
39+
return params.map((param, index) => {
40+
const struct = structs[index];
41+
const map = paramMap(param)[type];
42+
return map[struct] ? map[struct](param) || map['default'](param) : param
43+
})
44+
}
45+
46+
module.exports = {
47+
setDataStructure
48+
}

common/utils/withTimeLog.js

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const v8 = require("v8");
22
const { getFileSize } = require("./sizeUtil");
33
const { isSameData } = require("./isSameData");
4+
const { setDataStructure} = require('./parseStructure')
45

56
/**
67
* 执行并输出时间和内存
@@ -9,12 +10,13 @@ const { isSameData } = require("./isSameData");
910
* @param compare
1011
* @returns {{预期结果: string, 执行结果: string, 内存占用: string, 测试结果: (string), 执行用时: string}}
1112
*/
12-
function withTimeLog(fnName, param, compare) {
13+
function withTimeLog(fnName, param, compare, compareStruct) {
1314
// 记录开始时间
1415
const startTime = performance.now();
1516
// 获取函数执行前的内存使用情况
1617
const startHeapStatsArray = v8.getHeapSpaceStatistics()
1718
const callVal = fnName(...param)
19+
const [pasedCompareArr] = setDataStructure([callVal], compareStruct, 'return')
1820
// 获取函数执行后的内存使用情况
1921
const endHeapStatsArray = v8.getHeapSpaceStatistics()
2022
// 记录结束时间
@@ -23,18 +25,22 @@ function withTimeLog(fnName, param, compare) {
2325
const endHeapStats = endHeapStatsArray.reduce((prev, curr) => prev += curr.space_used_size, 0)
2426

2527
return {
26-
'测试结果': isSameData(callVal, compare) ? '通过' : '未通过',
28+
'测试结果': isSameData(pasedCompareArr, compare) ? '通过' : '未通过',
2729
'预期结果': JSON.stringify(compare),
28-
'执行结果': JSON.stringify(callVal),
30+
'执行结果': JSON.stringify(pasedCompareArr),
2931
'执行用时': Number(endTime - startTime).toFixed(4) + 'ms',
3032
'内存占用': getFileSize(endHeapStats - startHeapStats)
3133
}
3234
}
3335

34-
function showLogs(fnName, paramArr, compareArr) {
36+
function showLogs(fnName, paramMap, compareMap) {
3537
let logsItems = []
38+
const {data: paramArr, structure: paramStruct} = paramMap;
39+
const {data: compareArr, structrue: compareStruct} = compareMap;
40+
3641
paramArr.forEach((param, index) => {
37-
const logItem = withTimeLog(fnName, param, compareArr[index])
42+
const pasedParma = setDataStructure(param, paramStruct);
43+
const logItem = withTimeLog(fnName, pasedParma, compareArr[index], compareStruct)
3844
logsItems.push(logItem)
3945
})
4046
console.table(logsItems)

0 commit comments

Comments
 (0)