news 2026/9/8 22:26:07

freeCodeCamp JavaScript 每日挑战 Challenge 27:矩阵顺时针旋转 90 度(Matrix Rotate)实现详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
freeCodeCamp JavaScript 每日挑战 Challenge 27:矩阵顺时针旋转 90 度(Matrix Rotate)实现详解

freeCodeCamp JavaScript 每日挑战 Challenge 27:矩阵顺时针旋转 90 度(Matrix Rotate)实现详解

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

本篇以 freeCodeCamp 课程库中的 JavaScript 每日编程挑战 "Challenge 27: Matrix Rotate"(挑战定义文件)为主体,完整给出题目、测试用例与参考解法,并从源码级索引映射角度剖析"顺时针旋转 90 度"的核心公式,最后补充一个更直观的"转置 + 反转"实现思路,帮助读者掌握二维数组(矩阵)在原地索引变换下的旋转技巧。

一、题目定位与元信息

该挑战属于daily-coding-challenges-javascript代码块,是 freeCodeCamp 面向 JavaScript 的每日练习序列之一。其前置元信息(front matter)如下:

id: 68adce01c0e1144d0a90295a title: "Challenge 27: Matrix Rotate" challengeType: 28 dashedName: challenge-27

其中challengeType: 28是理解这道题运行机制的关键。在共享配置 challenge-types.ts 中可以确认该数值含义:

const dailyChallengeJs = 28;

由此可知:

  • challengeType28dailyChallengeJs)表示这是一个JavaScript 每日编程挑战
  • 从该文件的viewTypes映射看,dailyChallengeJs对应的视图是'classic'(经典编辑器视图),即读者会在熟悉的单文件代码编辑框中作答;
  • submitTypes映射看,其提交方式为'tests',意味着答案会通过与题目文件# --hints--段中列出的assert测试用例逐一比对来判分。

这些机制决定了本文的验证方式:只要你的rotate函数能稳定通过全部断言,即视为完成挑战。挑战在代码块中的排序可在 块结构文件 中查到,它位于 Challenge 26(IPv4 Validator)之后、Challenge 28(Roman Numeral Parser)之前。

二、题目描述:顺时针旋转 90 度

题目原文要求:

给定一个矩阵(一个数组的数组),将矩阵顺时针旋转 90 度并返回。例如给定[[1, 2], [3, 4]],它看起来像:

12
34

你应当返回[[3, 1], [4, 2]],看起来像:

31
42

核心目标:输入matrix(二维数组),输出一个新矩阵,其内容是原矩阵整体顺时针旋转 90 度的结果。注意题目要求"返回"结果矩阵,而非在原数组上原地修改,因此实现时通常构造一个新的结果数组更安全。

三、测试用例(完整继承题目断言)

题目# --hints--段给出了 4 组必须通过的断言,完整列出如下:

// 1x1 矩阵:旋转后保持不变 assert.deepEqual(rotate([[1]]), [[1]]); // 2x2 矩阵 assert.deepEqual(rotate([[1, 2], [3, 4]]), [[3, 1], [4, 2]]); // 3x3 矩阵 assert.deepEqual( rotate([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), [[7, 4, 1], [8, 5, 2], [9, 6, 3]] ); // 含重复值的 3x3 矩阵 assert.deepEqual( rotate([[0, 1, 0], [1, 0, 1], [0, 0, 0]]), [[0, 1, 0], [0, 0, 1], [0, 1, 0]] );

这 4 组用例覆盖了典型边界与常规情形:1x1退化矩阵、2x2小矩阵、标准3x3矩阵,以及含重复值的矩阵(后者能暴露索引计算错误——一旦行列映射写错,重复值会让错误结果"看起来对",是很好的自检用例)。

四、种子代码

题目# --seed-contents--段提供了初始骨架,默认实现只是原样返回输入,需要你在其中填入真正的旋转逻辑:

function rotate(matrix) { return matrix; }

五、参考解法:双循环 + 索引映射公式

题目# --solutions--段给出的标准实现如下:

function rotate(matrix) { const n = matrix.length; const result = Array.from({ length: n }, () => Array(n).fill(0)); for (let i = 0; i < n; i++) { for (let j = 0; j < n; j++) { result[j][n - 1 - i] = matrix[i][j]; } } return result; }

下面逐步拆解其设计与数学依据。

5.1 构造同尺寸结果矩阵

const n = matrix.length; const result = Array.from({ length: n }, () => Array(n).fill(0));

这里假设输入为正方形矩阵(n x n,题目四个用例均为方阵)。Array.from({ length: n }, () => Array(n).fill(0))生成一个n行、每行n列且初始值全为0的新二维数组。之所以用Array.from的回调方式逐行new出一个新数组,是为了避免"所有行共享同一个数组引用"的经典陷阱——直接写Array(n).fill(Array(n))会让n行指向同一个内层数组,赋值时互相覆盖。

5.2 核心映射:result[j][n - 1 - i] = matrix[i][j]

这是整个算法的灵魂,也是最容易写错的地方。设原矩阵坐标为(i, j)(第i行、第j列),顺时针旋转 90 度后,该元素落到新矩阵的第j行、第n - 1 - i列。

3x3用例逐格验证这一公式(n = 3):

原坐标 (i, j)原值新坐标 (j, n-1-i)新值落点
(0,0)1(0, 2)result[0][2] = 1
(0,1)2(1, 2)result[1][2] = 2
(0,2)3(2, 2)result[2][2] = 3
(1,0)4(0, 1)result[0][1] = 4
(1,1)5(1, 1)result[1][1] = 5
(2,0)7(0, 0)result[0][0] = 7

最终result第一行为[7, 4, 1],与期望输出[[7, 4, 1], [8, 5, 2], [9, 6, 3]]的首行完全一致,验证了公式正确性。

理解这个映射的几何直觉:原矩阵的最左一列i0n-1j=0)在顺时针旋转 90 度后会成为新矩阵的最上一行。以j=0代入公式得到result[0][n-1-i] = matrix[i][0]——即原第一列从"上到下"的元素,依次填到新矩阵第一行从"右到左"的位置,正是顺时针旋转的直观表现。

5.3 复杂度

该实现为双循环遍历全部n x n个元素,时间复杂度 O(n²),空间复杂度 O(n²)(新建一个结果矩阵)。对于方阵旋转而言这已是渐近最优——每个元素都必须被访问并重新放置一次。

六、另一种等价思路:转置 + 逐行反转

除直接索引映射外,顺时针旋转 90 度还可拆解为两个更易记忆的步骤:先沿主对角线转置,再对每一行做左右反转。以下实现与上述解法结果等价,可作为交叉验证:

function rotate(matrix) { const n = matrix.length; // 步骤 1:沿主对角线转置(行列互换) const transposed = matrix.map((row, i) => row.map((_, j) => matrix[j][i])); // 步骤 2:反转每一行 return transposed.map(row => row.reverse()); }

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]验证:

  • 转置后得到[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
  • 每行反转后得到[[7, 4, 1], [8, 5, 2], [9, 6, 3]],与期望输出完全一致。

两种写法都能通过第三节的assert.deepEqual断言,读者可按阅读习惯任选其一。

七、边界与适用前提

  • 方阵假设:参考解法以matrix.length作为统一边长n,默认输入是正方形矩阵。题目全部用例均为方阵,因此该假设成立。
  • 返回值语义:题目要求"返回"新矩阵,参考解法不修改入参,符合预期;若需在原数组上原地旋转,则需额外的交换技巧,但非本题要求。
  • 1x1退化:当n = 1时,公式result[0][0] = matrix[0][0]自然成立,无需特殊处理,这也是第一条断言rotate([[1]]) === [[1]]能被满足的原因。
  • 判分方式:结合 challenge-types.ts 中dailyChallengeJssubmitTypes'tests'可确认,作答最终由题目文件内列出的断言集合判定,因此把 4 组用例全部跑通即代表实现正确。

八、小结

本挑战要求实现一个将二维矩阵顺时针旋转 90 度并返回新矩阵的rotate函数。核心是掌握索引映射公式result[j][n - 1 - i] = matrix[i][j],理解"原最左列旋转后成为新最上行"的几何直觉;等价地也可采用"主对角线转置 + 逐行反转"的两步法。该函数属于 freeCodeCamp JavaScript 每日挑战(challengeType: 28)序列中的第 27 题,通过题目内置的assert断言即可完整验证实现的正确性。

【免费下载链接】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/8 22:24:07

RPCS3 自动更新完整指南:查版本、选通道、三步开启并验证

RPCS3 自动更新完整指南&#xff1a;查版本、选通道、三步开启并验证 【免费下载链接】rpcs3 PlayStation 3 emulator and debugger 项目地址: https://gitcode.com/GitHub_Trending/rp/rpcs3 本文带你走一遍 RPCS3 内置的更新系统&#xff1a;如何查看当前版本、分支与…

作者头像 李华
网站建设 2026/9/8 22:23:38

Python OpenCV实现几何形状检测与尺寸测量完整指南

简介&#xff1a;这套方案基于OpenCV实现图像中几何形状的检测与尺寸测量&#xff0c;面向图像处理初学者及OpenCV开发者。核心思路采用pixels per metric ratio&#xff08;每度量比的像素&#xff09;比例尺&#xff0c;通过已知物体的实际长度与像素数量换算像素与物理单位的…

作者头像 李华
网站建设 2026/9/8 22:23:10

福建全要素矢量数据预处理五步法:从坐标校验到拓扑修复

简介&#xff1a;2021年福建省基础地理信息矢量数据集是一套面向 ArcGIS 使用者的地理数据素材&#xff0c;适用于地图制图、空间分析与规划设计等场景&#xff0c;覆盖路网、水网、建筑、土地利用和行政区划边界等常用图层&#xff0c;统一采用 WGS84 坐标&#xff0c;无需额外…

作者头像 李华
网站建设 2026/9/8 22:21:25

硬件加密与软件加密实战选型指南:从芯片启动到量产烧录

1. 这不是“选哪个更好”的选择题&#xff0c;而是“在哪用、怎么用、为什么必须分清楚”的实战判断题芯片硬件加密和软件加密&#xff0c;这两个词在嵌入式开发、IoT设备安全、工业控制器选型甚至消费电子量产评审会上&#xff0c;几乎每天都会被工程师拎出来反复掰扯。我做ST…

作者头像 李华
网站建设 2026/9/8 22:18:19

半年转行机器人工程师:从零到项目实战的完整学习路线

很多朋友问我&#xff0c;怎么才能在半年内转行或者入行成为机器人工程师。说实话&#xff0c;这个目标有点野心&#xff0c;但绝不是白日做梦。我自己当年就是从机械专业硬生生转过来的&#xff0c;期间走了不少弯路&#xff0c;也踩过不少坑&#xff0c;现在想想&#xff0c;…

作者头像 李华