
我最近在刷牛客网的前端题刷到FED37数组反转的时候第一反应是这也太简单了吧JS里一个reverse()不就完事了但等我真正打算把这题吃透、写一个HTML页面来演示反转过程的时候才发现里面有不少值得掰开揉碎讲的东西。加上这几天我一直在手机腾讯元宝里用DeepSeek的深度思考模式辅助刷题这题就是典型的看着简单、越挖越深的样本。这篇文章就把我的完整实操过程记录下来从FED37的考点拆解到多种反转实现到整份HTML页面代码再到我用DeepSeek辅助推理时的对话实录和踩坑心得。不管是刚准备笔试的初学者还是在准备面试的前端开发者都能从中找到自己能直接拿去用的东西。1. 腾讯元宝里的DeepSeek怎么就成了我的刷题搭子1.1 深度思考模式对我这种一知半解的人最有价值先说工具。牛客网刷题时我手机里常年挂着腾讯元宝模型直接切到DeepSeek平时遇到看不明白的题解、没搞懂的知识点就往里一扔。相比普通AI问答模式DeepSeek的深度思考模式最打动我的一点是它不会直接甩答案而是在回答前先输出一大段推理过程把一个有点经验的工程师看到这道题之后脑子里闪过的东西完完整整摊开给你看。这正好治我的老毛病——以前刷题经常出现看答案全懂合上答案就懵的情况。普通问答模式只告诉我用reverse()就行深度思考模式则会告诉我为什么能想到用reverse()如果不能用API怎么办题目里这句话是不是在暗示原地反转。这些东西恰恰是面试时最值钱的部分。1.2 用元宝刷题前的准备和一个小坑配置上没什么门槛手机装好腾讯元宝登录后用模型切换功能把默认模型切到DeepSeek即可。网页端和App端都能用我惯用App因为刷题时随手拍照、复制题目片段都方便得多。不过我第一次切换时确实弹过一个安装环境异常的提示当时以为是模型包没下好后来发现多半是版本旧了或者网络抽风把App升级到最新版本、清理一次缓存再重开问题就消失了。如果你也遇到类似提示先别慌升级版本和换个网络环境是最高频的解法。准备工作做完之后我就拿着牛客FED37这道题进场了。2. FED37数组反转题目背后藏着哪些考点2.1 先还原一下原题长什么样牛客网的FED系列是前端方向的专项练习FED37这题属于数组基础操作。题目描述大致是这样将数组 arr 中的元素反转。例如输入 [1, 2, 3, 4]输出 [4, 3, 2, 1]。 要求实现一个函数优先考虑在原数组上操作不要借助额外的数组空间。平台要求的交付物是一个函数形如function reverseArray(arr) { // 在这里补全代码 }函数返回的结果会被判定器拿去和预期输出比对。这题在牛客上的通过率并不低但有意思的地方在于越是这种基础题越能拉开人和人的差距。有人一行reverse()交上去完事有人会追问题目里在原数组上操作到底是什么意思还有人能主动把时间复杂度和空间复杂度说清楚——后者在面试里拿到的评价通常比前者高一个档次。2.2 考点拆解不只考API更考原理把FED37放在面试官视角下它其实至少覆盖了三个层面的知识点第一数组API的熟练度。reverse()是不是存在、怎么用、返回值是什么这是最表层的东西。第二引用类型的理解。JavaScript里数组是引用类型函数的参数传的是引用。你在函数里改了实参外面的原数组也会跟着变。很多人在原地反转和复制后反转之间傻傻分不清本质是对引用传递的理解不够透。第三手写算法的基本功。当题目要求不要用额外数组时能不能立刻想到双指针交换就检验你有没有真正写过底层逻辑了。这也是面试官最喜欢追问的方向。3. 先别急着写HTML把反转函数本身吃透3.1 解法一一行reverse()的利弊function reverseArray(arr) { return arr.reverse(); }这是最直观的写法。JS引擎比如V8对reverse()做了底层优化性能很好代码可读性也最高。但这里有两个隐藏知识点恰恰是新手最容易翻车的地方。第一个reverse()是原地反转它操作的是原数组本身同时返回的值也是这个数组的引用。也就是说arr.reverse()执行完你手里的arr已经变了。这看起来在原地操作的题目要求下反而是优势但在日常开发里如果你不希望原数据被修改这就很危险。第二个牛客判定器到底认不认一行reverse()。实话实说很多写题平台是认的但只要面试官坐在你对面他大概率会追问一句如果不用原生reverse()你怎么实现。到这一步卡壳的人特别多。3.2 解法二双指针原地交换的手写实现双指针是手写反转的标准答案也是我最终在HTML页面里采用的方案function reverseArray(arr) { let left 0; let right arr.length - 1; while (left right) { // 交换左右指针对应的元素 const tmp arr[left]; arr[left] arr[right]; arr[right] tmp; left; right--; } return arr; }原理一句话一个指针指向头一个指针指向尾每次交换两个位置的元素然后头指针往右走一步、尾指针往左走一步直到两个指针相遇或者错位。整个过程中只用到了一个临时变量tmp空间复杂度是O(1)完全满足不借助额外数组空间的约束。我第一版写的条件其实是while (left right)自己测的时候发现没啥问题但后来看DeepSeek的思考链里特意提醒了一句等于的时候不需要交换——我琢磨了一下确实如果数组长度是奇数两个指针最终会同时指向中间那个元素它和自己交换等于白做一次操作。用既省一次循环逻辑上也更干净。3.3 解法三不修改原数组的反转变体面试官非常容易追问的另一个方向是如果我不想改变原数组只想要一个新数组你会怎么写常见的实现有三种// 方式1slice先复制再reverse function reverseArray(arr) { return arr.slice().reverse(); } // 方式2反向遍历逐个push function reverseArray(arr) { const result []; for (let i arr.length - 1; i 0; i--) { result.push(arr[i]); } return result; } // 方式3reduce spread偏炫技不推荐在面试里主动用 function reverseArray(arr) { return arr.reduce((acc, cur) [cur, ...acc], []); }这三种的共同点是都不会动原数组。注意arr.slice().reverse()里那个slice()很关键——先复制出一个新数组再在新数组上反转。如果你写的是arr.slice().reverse()那是安全的如果你写arr.reverse()原数组就没了。3.4 三种方案怎么选一个表格说清楚实现方案是否修改原数组时间复杂度空间复杂度最适用的场景arr.reverse()是O(n)引擎层已优化O(1)明确要求原地反转追求简洁时双指针手写是O(n)O(1)面试手写算法展示原理理解slice().reverse()否O(n)O(n)生产环境需要保留原数据时反向遍历push否O(n)O(n)想展示不依赖API也能实现时我的建议是平时刷题四种都要会写面试时优先给双指针方案然后把reverse()的实现原理和原地修改这个特性作为补充信息主动说出来面试官的好感度会明显不一样。4. 完整的HTML实现输入、反转、展示一条龙4.1 页面结构与交互逻辑怎么设计牛客OJ上只要交函数就行但既然标题写了HTML实现那就把整个交互页做出来。我的设计思路很直接一个输入框让用户输入数组元素用英文逗号分隔一个按钮点击后触发反转逻辑一个结果展示区域逆序渲染出反转后的数组交互逻辑的核心是输入解析拿到输入框的字符串后先按逗号split成数组再做一次trim去掉空格顺手用Number()尝试转成数字转不了的就保留原字符串。这样用户输入1,2,3,4得到数字数组输入a,b,c也能正常反转字符串数组容错性好得多。4.2 完整可运行的HTML代码下面是我实际跑通的完整页面直接存成.html文件双击就能用!DOCTYPE html html langzh-cn head meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleFED37 数组反转练习/title style * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: PingFang SC, Microsoft YaHei, sans-serif; background: #f5f6fa; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .card { background: #fff; border-radius: 12px; padding: 32px; width: 420px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); } .card h1 { font-size: 20px; margin-bottom: 8px; color: #1a1a2e; } .card .desc { font-size: 14px; color: #888; margin-bottom: 20px; } .card label { display: block; font-size: 14px; margin-bottom: 6px; color: #333; } .card input { width: 100%; padding: 10px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; margin-bottom: 12px; outline: none; } .card input:focus { border-color: #2d6cdf; } .card button { width: 100%; padding: 10px 0; background: #2d6cdf; color: #fff; border: none; border-radius: 6px; font-size: 15px; cursor: pointer; margin-bottom: 16px; transition: background 0.2s; } .card button:hover { background: #1e56b3; } .result-box { background: #f0f4ff; border-radius: 6px; padding: 16px; font-size: 16px; color: #1a1a2e; min-height: 60px; } .result-box .tag { font-size: 12px; color: #888; margin-bottom: 4px; } #result { word-break: break-all; } /style /head body div classcard h1FED37 数组反转/h1 p classdesc牛客网前端练习 · 输入数组元素点击按钮反转/p label forarrayInput数组用英文逗号分隔/label input typetext idarrayInput placeholder例如1,2,3,4 value1,2,3,4 button idreverseBtn反转数组/button div classresult-box div classtag反转结果/div div idresult等待输入.../div /div /div script // 双指针原地反转与牛客FED37要求一致 function reverseArrayInPlace(arr) { let left 0; let right arr.length - 1; while (left right) { const tmp arr[left]; arr[left] arr[right]; arr[right] tmp; left; right--; } return arr; } document.getElementById(reverseBtn).addEventListener(click, function () { const input document.getElementById(arrayInput).value.trim(); const resultBox document.getElementById(result); if (!input) { resultBox.textContent 请输入数组元素; return; } const arr input.split(,).map(function (item) { const trimmed item.trim(); const num Number(trimmed); return isNaN(num) ? trimmed : num; }); const reversed reverseArrayInPlace(arr); resultBox.textContent [ reversed.join(, ) ]; }); /script /body /html4.3 跑起来之后要注意的细节我实际测试时发现几个容易被忽略的点第一输入框里的空格处理。很多用户会习惯性输入1, 2, 3这种带空格的格式如果直接split(,)得到的数组是[1, 2, 3]反转后输出就带着空格很丑。所以map阶段一定要做trim()。第二空输入不能崩。我在按钮事件里先做了trim()如果为空就直接提示请输入数组元素避免后面对一个空字符串做split(,)得到[]这种脏数据。第三反转数组和反转字符串千万别混。我在测试时一度想复用这页代码去反转一个纯字符串结果发现abc.split(,)根本切不动——字符串反转是另一个思路需要先split()切分成字符数组再反转。这俩问题在面试里也经常被拿来混淆提问。5. 我在元宝里和DeepSeek的真实对话记录5.1 我是怎么把牛客题喂给AI的与其空谈AI辅助刷题不如直接放一段我实际使用的提问过程。当时我把题目和我的困惑整理成一段话扔给了元宝里的DeepSeek我在牛客网刷FED37数组反转。题目是将数组arr中的元素反转例如[1,2,3,4]变为[4,3,2,1]要求实现一个函数尽量在原数组上操作不借助额外数组空间。我直接写arr.reverse()交上去会不会有问题如果面试官追问手写实现我应该怎么答这里有个经验提问时一定要把题目来源完整要求我的主观困惑三样都说清楚。只贴一行题面AI给出的答案大概率是泛泛的把我在牛客上刷的要求原地反转这些上下文带上它才能给出针对性的分析。5.2 DeepSeek思考链里我印象最深的三个点DeepSeek在深度思考模式下先输出了一段推理我不是逐字复制的但它在推理链里提到的三个点让我印象很深。第一它主动区分了牛客判定器的验收标准和面试官的考察标准。它的意思是如果牛客只比对返回结果reverse()大概率能过但面试场景里考察的是你能不能脱离API手写核心逻辑。所以稳妥的策略是会写reverse()更要会写双指针。第二它提醒我注意reverse()的副作用——原地反转既是题目的要求也是一个隐性陷阱。如果题目哪天变成返回一个新的反转数组直接调reverse()就会把原数组搞坏。这让我意识到刷题不能只追求答案对要考虑题目背后对数据变动的隐含约定。第三它补充了偶数长度/奇数长度数组对终止条件的影响。奇数个数时最中间的指针指向自己偶数个数时两个指针会擦肩而过。这就解释了为什么双指针的循环条件要用left right而不是left right——等号在数学上没毛病工程上却多了一轮无意义操作。5.3 顺着AI的回答挖出的面试追问DeepSeek在回答末尾还主动列了几个面试官可能会追问的问题我原封不动记下来了如果数组里放的是对象反转后对象的引用关系会变吗怎样在不修改原数组的前提下拿到反转结果reverse()的时间复杂度是多少手写双指针的时间复杂度又是多少如果输入不是数组而是一个类数组对象你的函数会出什么问题这几个问题我之前从来没想过。第一个问题的答案是反转的是数组元素的排列顺序元素如果是对象对象的引用本体不会被复制或深拷贝也就是说反转前后数组里每个元素的引用地址不变只是顺序变了。想明白这一点很多数组套对象的题目思路都会清爽很多。6. 面试官视角数组反转的加分项与避坑清单6.1 高频追问和不翻车回答把FED37放到实战面试里我整理了一套高频追问的应答思路追问1你用的reverse()会改变原数组吗回答要点会。reverse()是原地操作返回的也是原数组的引用。所以如果要求保留原数据得先slice()再reverse()。追问2手写一个原地反转说说复杂度和边界。回答要点双指针。左右指针向中间靠拢交换元素循环条件left right。时间复杂度O(n)空间复杂度O(1)。边界上注意空数组、单元素数组、奇数长度数组。追问3如果输入是[1, 5, 3, 9]你的代码跑完是什么过程回答要点当场画状态最好口头描述也行——首尾交换9和1换、指针内缩5和3换、leftright停止得到[9, 3, 5, 1]。这题一旦能脱口而出面试官基本就知道你是真的理解了。追问4数组元素是对象反转后foreach遍历顺序变成了什么回答要点遍历顺序变成从最后一个元素到第一个元素但每个元素的对象引用没变。如果需要深拷贝那是另一套方案。6.2 数组反转避坑清单坑出现原因正确处理以为reverse()返回一个新数组对返回值理解不到位它返回的是原数组的引用原数组已经被修改双指针循环条件写成了没想清中间指针是否需要自交换用等于时停止split(,)后元素带空格用户输入1, 2, 3map时先trim()再处理输入空串导致数组变[]没有提前判空trim后为空直接return数字与字符串混用时转成了NaN无脑Number()用isNaN兜底转不了就保留原字符串以为对象会被反转时被复制对引用类型理解不透反转只改变顺序不复制对象本身6.3 关于AI辅助刷题我的几条实操心得写到这里说点个人的真实体会。AI辅助刷题确实效率高但前提是你要带着脑子用。我的三条原则很简单第一先自己动手写再让AI点评。直接甩题给AI要答案短期刷题数量上去了面试一紧张照样写不出来。我自己是这个流程先在牛客上提交一版再把我和AI的代码对比让它帮我找出我写的和它写的差在哪、为什么差。第二主动要求AI暴露思考链。在元宝里用DeepSeek时深度思考模式默认会展开推理过程这一步千万别跳过。很多题的价值不在最终代码而在看到题目后如何一步步接近答案的推理路径。把推理链看懂比拿到正确代码有用十倍。第三把AI当成出题陪练。我习惯在解完一题后让它换个条件再问我比如如果数组里有空值如果要求递归实现如果数组长度是百万级性能怎么办。这些问题刷完一遍回头再看FED37这种基础题基本不会再有死角。我自己的体会是这题尽管叫数组反转真正的价值在于把API调用、引用类型理解、手写算法能力以及边界处理这几个基本功串在了一起。能独立把这些讲明白说明这题没有白刷。