news 2026/9/10 10:08:48

freeCodeCamp 每日编码挑战精讲:Challenge 272 矩阵转置(Transposed Matrix)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
freeCodeCamp 每日编码挑战精讲:Challenge 272 矩阵转置(Transposed Matrix)

freeCodeCamp 每日编码挑战精讲:Challenge 272 矩阵转置(Transposed Matrix)

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

本篇技术指南以 freeCodeCamp 每日编码挑战系列(Daily Coding Challenges)中的第 272 题——Transposed Matrix(矩阵转置)为线索,完整拆解题目要求、5 个测试断言、种子代码与官方参考解法,并结合 freeCodeCamp 开源仓库中该挑战的真实配置与前端实现,讲解矩阵转置算法的推导过程与 JavaScript 实现技巧。读完本文,你不仅能通过这道挑战,还能理解assert.deepEqual式测试驱动的解题流程,以及每日挑战模块在 freeCodeCamp 代码库中的组织方式。

挑战背景:freeCodeCamp 每日编码挑战体系

本挑战位于 freeCodeCamp 课程仓库的curriculum/challenges/english/blocks/daily-coding-challenges-javascript/目录下,文件名为 69e2383af7832c8032603b8e.md(以挑战 id 命名)。根据块配置文件 daily-coding-challenges-javascript.json,该块共收录365 道挑战(Challenge 1 至 Challenge 365),本挑战是其中第 272 道,编号位于 Challenge 271(Medication Reminder)与 Challenge 273(ISBN-13 Validator)之间。

块的元数据揭示了该挑战的运行环境:

配置项含义
dashedNamedaily-coding-challenges-javascript块路由标识
challengeType(挑战内)28对应dailyChallengeJs类型
usesMultifileEditortrue使用多文件编辑器
helpCategoryJavaScript帮助分类
disableLoopProtectTeststrue禁用循环保护测试
blockLayoutlegacy-challenge-list旧版挑战列表布局

挑战类型28的定义可以在 challenge-types.ts 中找到:const dailyChallengeJs = 28;,与其对应的是dailyChallengePy = 29(Python 版本)。同一文件还说明:该类型的视图为classic(经典编辑器视图),提交类型为tests(运行测试判定),并且getDailyCodingChallengeLanguage会将类型 28 映射为'javascript'。也就是说,这道矩阵转置题正是以"运行单元测试"的方式自动评分的。

题目要求:理解矩阵转置

挑战描述(--description--段)如下:

给定一个矩阵(数组的数组),返回它的转置版本。

转置矩阵即交换行与列。例如:位于索引[0, 1]的值应移动到索引[1, 0]

换言之,给定一个m × n的矩阵(m 行 n 列),转置后得到一个n × m的矩阵:原矩阵第i行第j列的元素,在新矩阵中位于第j行第i列。数学上可记为result[j][i] = matrix[i][j]

题目给出的示例输入与期望输出:

[ [1, 2, 3], [4, 5, 6] ]

转置后返回:

[ [1, 4], [2, 5], [3, 6] ]

可以看到,原来 2 行 3 列的矩阵变成了 3 行 2 列:原第一行[1, 2, 3]变成了新矩阵的第一列,原第二行[4, 5, 6]变成了第二列。

测试用例:5 组断言逐条解析

本挑战共提供 5 组测试(--hints--段),全部使用assert.deepEqual进行深比较——即逐元素比较两个数组的结构与值,而非比较引用地址。这意味着返回的数组必须是全新构建的,直接return matrix(种子代码的默认行为)必然无法通过任何测试。

测试 1:基础 2×3 矩阵

assert.deepEqual(transpose([[1, 2, 3], [4, 5, 6]]), [[1, 4], [2, 5], [3, 6]]);

transpose([[1, 2, 3], [4, 5, 6]])应返回[[1, 4], [2, 5], [3, 6]]

测试 2:3×2 矩阵(与测试 1 互为逆运算)

assert.deepEqual(transpose([[1, 2], [3, 4], [5, 6]]), [[1, 3, 5], [2, 4, 6]]);

3 行 2 列转置为 2 行 3 列,行数、列数互换。

测试 3:4×2 矩阵

assert.deepEqual(transpose([[1, 2], [3, 4], [5, 6], [7, 8]]), [[1, 3, 5, 7], [2, 4, 6, 8]]);

进一步验证非方阵场景:4 行 2 列 → 2 行 4 列。

测试 4:3×3 字符串矩阵

assert.deepEqual(transpose([["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"], ["j", "k", "l"]]), [["a", "d", "g", "j"], ["b", "e", "h", "k"], ["c", "f", "i", "l"]]);

注意此例实为 4 行 3 列(4 个内层数组,每个含 3 个字符串),转置后为 3 行 4 列。它证明该函数必须支持字符串元素,与元素类型无关。

测试 5:5×4 布尔矩阵

assert.deepEqual(transpose([[true, false, true, false], [false, true, false, true], [true, true, false, false], [false, false, true, true], [true, false, false, true]]), [[true, false, true, false, true], [false, true, true, false, false], [true, false, false, true, false], [false, true, false, true, true]]);

5 行 4 列转置为 4 行 5 列,元素为布尔值。综合来看,5 个测试覆盖了不同尺寸与不同元素类型(数字、字符串、布尔值),充分检验实现的通用性。

种子代码:从占位实现出发

挑战的初始代码(--seed----seed-contents--)为:

function transpose(matrix) { return matrix; }

占位实现直接返回原矩阵,功能上"什么都没做"。你的任务就是在函数体内填充转置逻辑,同时保持函数签名transpose(matrix)不变——测试正是通过这个名字来调用你的实现的。对于dailyChallengeJs(类型 28)挑战,前端使用classic视图渲染,提交时以tests类型运行上述断言。

官方解法:一行代码完成转置

本挑战的官方参考解法(--solutions--段)极为精炼:

function transpose(matrix) { return matrix[0].map((_, i) => matrix.map(row => row[i])); }

逐层拆解这行代码的运行机制:

  1. matrix[0]取矩阵的第一行,其长度即原矩阵的列数n
  2. 对第一行调用map((_, i) => ...),以索引i从 0 到n-1迭代——这决定了新矩阵的行数等于n
  3. 在回调中执行matrix.map(row => row[i]):遍历原矩阵的每一行,取出每行中第i列的元素,组成新矩阵的第i行。

例如对[[1, 2, 3], [4, 5, 6]]

  • i = 0时,matrix.map(row => row[0])得到[1, 4](各行的第一个元素);
  • i = 1时,得到[2, 5]
  • i = 2时,得到[3, 6]

最终结果为[[1, 4], [2, 5], [3, 6]],与题目期望完全一致。这个解法的巧妙之处在于:用"取第一行遍历"隐式确定了列数,再用"内层 map 逐行取第 i 个元素"完成行列交换,两个map嵌套即完成了转置,无需显式书写任何循环变量或临时数组。

时间复杂度分析

该解法遍历了矩阵的全部m × n个元素一次,时间复杂度为O(m × n)(其中 m 为行数、n 为列数),是转置问题的最优线性下界——因为每个元素都必须移动到新位置。空间复杂度同样为O(m × n),因为必须构建一个全新的矩阵来存放结果(新矩阵与原矩阵共享元素引用,但对元素为原始类型(数字、字符串、布尔值)时,值完全独立)。

其他可行的实现思路

除官方解法外,以下两种思路同样可以通过全部测试,供对比理解:

思路一:显式双层循环

function transpose(matrix) { const rows = matrix.length; const cols = matrix[0].length; const result = []; for (let j = 0; j < cols; j++) { const newRow = []; for (let i = 0; i < rows; i++) { newRow.push(matrix[i][j]); } result.push(newRow); } return result; }

外层循环遍历列(j),内层循环遍历行(i),把matrix[i][j]逐元素搬运到result[j][i]。语义最直白,适合作为理解转置本质的教学版本。

思路二:reduce函数式写法

function transpose(matrix) { return matrix.reduce( (prev, row) => row.map((item, i) => [...(prev[i] || []), item]), [] ); }

每次遍历一行,把该行的每个元素追加到结果对应行的末尾。虽然可行,但频繁展开/重建数组,可读性与效率都不如官方解法,在此仅作拓展参考。

边界情况与常见陷阱

编写本题实现时,需要注意以下几点(均由测试结构与断言方式推导得出):

  • 不能原地修改并返回原矩阵assert.deepEqual比较的是值与结构,虽然原地转置方阵在数学上可行,但题目要求"返回转置版本",且测试传入的是字面量数组,原地修改同样会被检测出来(返回同一个引用虽能通过deepEqual值比较,但返回新数组才是标准做法,也能避免污染调用方数据)。
  • 必须处理非方阵:测试 1、2、3、5 都是非方阵(行数 ≠ 列数),因此不能简单交换行列索引后原地操作,必须创建行数 = 原列数、列数 = 原行数的新矩阵。
  • 元素类型无关性:测试覆盖数字、字符串、布尔值,实现中不要对元素做任何类型假设或运算。
  • 空矩阵与稀疏矩阵:题目及测试未涉及空数组,但若考虑健壮性,可先检查matrix.length === 0matrix[0].length === 0并返回空数组;官方解法在输入为空时会因访问matrix[0]而返回undefined,所以运行时保证输入非空即可。

挑战在前端的呈现与验证链路

理解这道题在 freeCodeCamp 学习平台上的完整运行链路,有助于把握它的评分方式:

  1. 数据来源:每日挑战按日期组织。前端路由组件 show-daily-coding-challenge.tsx 会请求${apiLocation}/daily-coding-challenge/day/${monthDay}获取当日挑战数据。
  2. 数据校验:返回的数据需通过 daily-coding-challenge-validator.ts 中定义的 Joi schema 校验——其中要求tests为包含texttestString的数组、challengeFiles包含文件内容、并记录challengeNumberdatetitledescription等字段,JavaScript 与 Python 两种语言的数据都必须齐备。
  3. 入口组件:学习地图页通过 widget.tsx 展示"今日挑战"与"挑战归档"两个入口按钮。
  4. 语言切换:classic 挑战模板(如 show.tsx 与 action-row.tsx)支持在 JavaScript 与 Python 之间切换语言,选择结果存入本地存储键dailyCodingChallengeLanguage

课程侧,挑战文件本身由 challenge-schema.js 校验,其中challengeType必须是 0~33 的整数;本挑战的28恰好落在dailyChallengeJs的取值上。此外isUpcomingChange: true表明该块属于"即将上线"的新内容,块结构由同目录 JSON 与curriculum.json统一管理。

总结

Challenge 272 "Transposed Matrix" 是一道典型的二维数组操作题:它要求把m × n矩阵的每个元素matrix[i][j]移动到result[j][i]。官方解法用matrix[0].map((_, i) => matrix.map(row => row[i]))一行代码实现,时间复杂度 O(m × n),兼顾简洁与高效。通过这道题,你既巩固了嵌套map与索引交换的核心技巧,也体验了 freeCodeCamp 每日编码挑战"描述 + 断言 + 种子代码 + 参考解法"的标准化练习流程——全部 5 组assert.deepEqual测试在浏览器内实时运行,通过即过关。如需查看本挑战的完整源文件,可直接阅读 69e2383af7832c8032603b8e.md,并参考同目录下其他 364 道挑战继续进阶练习。

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 10:08:30

基于FaceNet与PyQt5的人脸识别系统:从原理到工程实践

简介&#xff1a;面向毕业设计的人脸身份识别系统&#xff0c;基于 Python 与 PyQt5 开发&#xff0c;内置图形化操作界面&#xff0c;适合计算机相关专业学生用于课程设计、毕业设计或深度学习项目实践&#xff1b;系统以 FaceNet 预训练模型为核心&#xff0c;结合 OpenCV 与…

作者头像 李华
网站建设 2026/9/10 10:08:01

cann/ge Graph Engine API构造函数与析构函数

构造函数和析构函数 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、Tensor…

作者头像 李华
网站建设 2026/9/10 10:05:27

STM32 RS485半双工通信时序控制与帧解析实战

简介&#xff1a;本资源是一套基于STM32F103的RS485通信与MODBUS-RTU协议实现的完整嵌入式开发工程&#xff0c;面向嵌入式初学者及工业通信入门开发者&#xff0c;解决多点工业总线通信中硬件驱动配置、协议帧解析与主从交互等核心问题。压缩包含75个文件&#xff0c;以34个C源…

作者头像 李华
网站建设 2026/9/10 10:03:31

【单片机课程设计/毕业设计】基于 STM32 的多传感器融合智能办公座椅系统设计 基于 STM32 的人体感知座椅灯光联动控制系统设计(018407)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华