LeetCode JS专栏刷题笔记(一)

一、前言

LeetCode 在前不久出了一个 JavaScript 专栏,这个专栏一个目的是为了非前端工程师学习 JS,另一个是为了前端工程师提升 JS 能力。

因此在这个专栏中,基本不涉及什么具体算法问题,都是一些 JS 的入门语法与常见的 JS 面试题, 但我在给朋友推荐该专栏时阻力非常大,绝大部分当看到是 LeetCode 链接时就直接失去了点击的欲望,认为里面都是十分烧脑的算法题,而实际题目远比想象中的简单,甚至远比平时面试题的解答都要简单。

由于整个专栏中的题目难易程度参差不齐,甚至有 HelloWorld 一类的题目,为了保证整体文章质量,不会对过于简单的题目进行讲解。

我写这篇文章的目的有以下几方面:

  1. 减缓一部分前端开发对 LeetCode 及算法的抗拒性
  2. 巩固及梳理自己的做题笔记
  3. 帮助刚入门或基础较差的前端工程师梳理实现思路

注: 本篇写于 2023-07-09,最早发表于掘金,因 CSDN 同步文章格式有问题,故重新发表。

二、算法题目

1. 记忆函数

LeetCode地址:2623. 记忆函数

请你编写一个函数,它接收另一个函数作为输入,并返回该函数的 记忆化 后的结果。

记忆函数 是一个对于相同的输入永远不会被调用两次的函数。相反,它将返回一个缓存值。

你可以假设有 3 个可能的输入函数:sumfibfactorial

  • sum 接收两个整型参数 ab ,并返回 a + b
  • fib 接收一个整型参数 n ,如果 n <= 1 则返回 1,否则返回 fib (n - 1) + fib (n - 2)
  • factorial 接收一个整型参数 n ,如果 n <= 1 则返回 1 ,否则返回 factorial(n - 1) * n

Pasted image 20230708224751.png

思路

这道题主要考察的是对于闭包的使用,闭包属于前端比较基础的问题,如果展开来讲篇幅会比较长,所以不在此讨论,对此没还有掌握的自行查阅资料。

知道这道题需要通过闭包进行缓存后,整体思路很清晰了,我们通过闭包维护一个变量,让输入的参数与计算后的值始终保持在内存中,保证不会被垃圾回收掉,再次调用时直接从缓存中取出值即可。

由于题目要求:相同输入参数不进行二次调用,直接返回缓存值(这实际就是一个纯函数:使用相同的输入始终会得到相同的输出),所以我们可以将每次调用的参数做为哈希表的 Key

如此,通过闭包创建 cached 哈希表,每次调用前将参数转为字符串进行访问 cached 中是否存在, 如果命中缓存,则直接返回,如果缓存中不存在则调用 fn 缓存结果后再返回。

具体实现

/*** @param {Function} fn*/
function memoize(fn) {// 创建缓存对象const map = new Map();return function(...args) {// 将参数转换为字符串// 可以通过 JSON.string、 args.join、 args.toString 等方法// 注意:虽然 Map 的 key 值可以是对象、数组,// 但是由于每次接收的参数列表都是一个全新的引用地址,所以不能直接作为 key 值const argsStr = args.join(',');// 如果没有命中缓存则进行计算后再返回if(!map.has(argsStr)){map.set(argsStr, fn(...args))}return map.get(argsStr)}
}

2.蜗牛排序

LeetCode地址:2624. 蜗牛排序

请你编写一段代码为所有数组实现 snail(rowsCount,colsCount) 方法,该方法将 1D 数组转换为以蜗牛排序的模式的 2D 数组。无效的输入值应该输出一个空数组。当 rowsCount * colsCount !==``nums.length 时。这个输入被认为是无效的。

蜗牛排序从左上角的单元格开始,从当前数组的第一个值开始。然后,它从上到下遍历第一列,接着移动到右边的下一列,并从下到上遍历它。将这种模式持续下去,每列交替变换遍历方向,直到覆盖整个数组。例如,当给定输入数组 [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15] ,当 rowsCount = 5colsCount = 4 时,需要输出矩阵如下图所示。注意,矩阵沿箭头方向对应于原数组中数字的顺序

Pasted image 20230708224539.png

思路

这道题纯纯的考察编码能力了,没有什么很特别的考点。

这道题的实现思路就是根据蜗牛排序的遍历规律,按顺序将给定的一维数组元素填充进二维数组中的对应位置。每次填充时,根据当前列的奇偶性来决定是向上还是向下移动一行,从而形成蜗牛排序的遍历路径。

具体实现

/*** @param {number} rowsCount* @param {number} colsCount* @return {Array<Array<number>>}*/
Array.prototype.snail = function(rowsCount, colsCount) {const n = this.length;if(rowsCount * colsCount !== n) return [];const array = [];for(let i = 0; i < rowsCount; i++) {array[i] = [];}// 以下是简化版的创建二维数组代码,但通过该方法实际效率不仅没有提升甚至还有所降低:// 由于.fill 与 .map 都会遍历一次数组,所以时间复杂度是:O(rowsCount * 2)// const array = new Array(rowsCount).fill(0).map(() => new Array(colsCount));let row = col = 0for(let i = 0; i < n; i++) {array[row][col] = this[i];// 通过奇偶性判断方向,如果是整数则说明应该向下移动,反之应该向上移动if(col % 2 === 0) {// 当 row === rowsCount - 1 时,说明当前已经到最后一行了// 如果到了最后一行,则向右移动到下一列,否则向下移动一行row === rowsCount - 1 ? col++ : row++} else {// 如果 row === 0, 则说明当前已经到第一行了// 如果 到了第一行,则向右移动到下一列,否则向上移动一行row === 0 ? col++ :  row--}}return array;
}

3.扁平化嵌套数组

LeetCode地址:2625. 扁平化嵌套数组

请你编写一个函数,它接收一个 多维数组 arr 和它的深度 n ,并返回该数组的 扁平化 后的结果。

多维数组 是一种包含整数或其他 多维数组 的递归数据结构。

数组 扁平化 是对数组的一种操作,定义是将原数组部分或全部子数组删除,并替换为该子数组中的实际元素。只有当嵌套的数组深度大于 n 时,才应该执行扁平化操作。第一层数组中元素的深度被认为是 0。

请在没有使用内置方法 Array.flat 的前提下解决这个问题。

Pasted image 20230708224952.png

思路

这是一道经典的面试题:手写 Array.proptype.flat 方法, 即手写拍平数组。

这道题我给出的解法是最常见的 DFS解法,但类似的,还可以使用 BFS、迭代 方法实现。

具体实现思路就是:通过递归并遍历数组的每个元素,如果是子元素是数组,则递归调用 flat 函数来进一步展开子数组。

通过使用递归和回溯的方式,可以逐层深入地处理多维数组,直到达到指定的展开深度。这种深度优先搜索的方法使得展开过程可以有效地处理多层嵌套的数组,并按照深度优先的顺序将元素依次展开到一维数组中。

具体实现

/*** @param {any[]} arr* @param {number} depth* @return {any[]}*/
var flat = function (arr, n) {if(n === 0) return arr;const array = [];for(let i = 0; i < arr.length; i++) {if(Array.isArray(arr[i])){// 使用 ES6 的 `...` 扩展运算符简化代码// flat返回的是下一层已展开的数组array.push(...flat(arr[i], n - 1))}else{array.push(arr[i]);}}return array;
};

4.函数防抖

LeetCode地址:2627. 函数防抖

请你编写一个函数,接收参数为另一个函数和一个以毫秒为单位的时间 t ,并返回该函数的 函数防抖 后的结果。

函数防抖 方法是一个函数,它的执行被延迟了 t 毫秒,如果在这个时间窗口内再次调用它,它的执行将被取消。你编写的防抖函数也应该接收传递的参数。

例如,假设 t = 50ms ,函数分别在 30ms60ms100ms 时调用。前两个函数调用将被取消,第三个函数调用将在 150ms 执行。如果改为 t = 35ms ,则第一个调用将被取消,第二个调用将在 95ms 执行,第三个调用将在 135ms 执行。

Pasted image 20230708232853.png

上图展示了了防抖函数是如何转换事件的。其中,每个矩形表示 100ms,反弹时间为 400ms。每种颜色代表一组不同的输入。

请在不使用 lodash 的 _.debounce() 函数的前提下解决该问题。

Pasted image 20230708232923.png

思路

同样是一道经典面试题:手写 防抖 函数,相比起实际面试中可能还会给出更复杂的业务场景,这个道题只要求实现基本功能即可。

debounce 主要功能是,在一定时间内频繁触发,只执行最后一次操作。

创建一个定时器,在 t 毫秒后执行方法,如果这段时间内再次触发,则直接清除掉上个定时器,重新计时即可。

具体实现

/*** @param {Function} fn* @param {number} t milliseconds* @return {Function}*/
var debounce = function(fn, t) {let timer = '';return function(...args) {clearInterval(timer)timer = setTimeout(()=> fn(...args),t)}
};

5.完全相等的 JSON 字符串

LeetCode地址:2628. 完全相等的 JSON 字符串

给定两个对象 o1o2 ,请你检查它们是否 完全相等

对于两个 完全相等 的对象,它们必须包含相同的键,并且相关的值也必须 完全相等 。如果两个对象通过了 '===' 相等性检查,它们也被认为是 完全相等 的。

你可以假设这两个对象都是 JSON.parse 的输出。换句话说,它们是有效的 JSON

请你在不使用 lodash 的 _.isEqual() 函数的前提下解决这个问题。

Pasted image 20230709011315.png

思路

由于通过 === 在判断两个对象是否相等时,判断的是两个对象的引用地址,所以必须通过递归的方式逐层解析到基本类型才能实现该功能。

比较完全相等主要是考虑 数组 与 对象 这两类引用类型的数据,如果是基本类型可直接通过 === 进行判断。

如果是数组或者是对象时,考虑到数组及对象中 可能还会嵌套对象、数组,所以需要递归判断每一个元素是否相等。

具体实现

/*** @param {any} o1* @param {any} o2* @return {boolean}*/
var getType = (val) => Object.prototype.toString.call(val);
var areDeeplyEqual = function (o1, o2) {// 如果两个对象类型不同,则值一定不同if (getType(o1) !== getType(o2)) return false;// 如果传入参是基本类型、或者是 null、undefined 等直接进行比较if (!o1 || !o2 || typeof o1 !== 'object') return o1 === o2;// 递归检查数组、对象if (Object.keys(o1).length !== Object.keys(o2).length) return false;for (const k in o1) if (!areDeeplyEqual(o1[k], o2[k])) return false;return true;
};

三、结语

由于算法讲解本身就很难通过 少量的语言就能表述清除,让文字通俗易懂更是难上加难,为了避免篇幅太长而导致放弃或者直接丢到收藏夹中吃灰,所以本篇只提取了 5 道题进行讲解。

算法的实现本身就多种多样的,我的个人见解未必是最优解,我非常欢迎读者对我在文章中提出的观点、方法或示例进行评价和反馈。这对于我个人的成长和进步非常重要,也有助于确保我传达的信息准确无误。所以,请不要犹豫,如果你有任何想法或建议,请在阅读文章后留下你的评论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/259742.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【c++ debug】记一次protobuf结构相关的coredump问题

文章目录 1. 问题现象2. 问题描述3. 问题分析4. 问题根因5. 问题修复6. 补充&#xff1a;类成员变量定义为引用类型 1. 问题现象 其中curr_lanes是一个目标上一帧的当前车道current_lanes_curr_lane是lane_id对应的LaneInfo信息现象&#xff1a;在lane_info->lane().success…

【Java面试】MongoDB

目录 1、mongodb是什么&#xff1f;2、mongodb特点什么是NoSQL数据库&#xff1f;NoSQL和RDBMS有什么区别&#xff1f;在哪些情况下使用和不使用NoSQL数据库&#xff1f;NoSQL数据库有哪些类型?启用备份故障恢复需要多久什么是master或primary什么是secondary或slave系列文章版…

多模态基础---BERT

1. BERT简介 BERT用于将一个输入的句子转换为word_embedding&#xff0c;本质上是多个Transformer的Encoder堆叠在一起。 其中单个Transformer Encoder结构如下&#xff1a; BERT-Base采用了12个Transformer Encoder。 BERT-large采用了24个Transformer Encoder。 2. BERT的…

VPX信号处理卡设计原理图:9-基于DSP TMS320C6678+FPGA XC7V690T的6U VPX信号处理卡 信号处理 无线电通信

一、概述 本板卡基于标准6U VPX 架构&#xff0c;为通用高性能信号处理平台&#xff0c;系我公司自主研发。板卡采用一片TI DSP TMS320C6678和一片Xilinx公司Virtex 7系列的FPGA XC7V690T-2FFG1761I作为主处理器&#xff0c;Xilinx 的Aritex XC7A200T作为辅助处理器。XC7A2…

JVS智能BI的ETL数据集实践:数据自动化分析的秘诀

数据集是JVS-智能BI中承载数据、使用数据、管理数据的基础&#xff0c;同样也是构建数据分析的基础。可以通俗地将其理解为数据库中的普通的表&#xff0c;它来源于智能的ETL数据加工工具&#xff0c;可以将数据集进行分析图表、统计报表、数字大屏、数据服务等制作。 数据集管…

ElasticSearch之Index Template 和Dynamic Template

写在前面 在ElasticSearch之Mapping 一文中我们一起看了es的dynamic mapping机制&#xff0c;通过该机制允许我们不需要显式的定义mapping信息&#xff0c;而是es根据插入的文档值来自动生成 &#xff0c;比如插入如下的文档&#xff1a; {"firstName": "Chan…

初识 Rust 语言

目录 前言一、Rust 的背景二、Rust的特性三、部署开发环境&#xff0c;编写一个简单demo1、在ubuntu 20.04部署环境2、编写demo测试 四、如何看待Linux内核引入Rust 前言 自Linux 6.1起&#xff0c;初始的Rust基础设施被添加到Linux内核中。此后为了使内核驱动程序能够用Rust编…

第13章 网络 Page744~746 asio核心类 ip::tcp::endPoint

2. ip::tcp::endpoint ip::tcp::socket用于连接TCP服务端的 async_connect()方法的第一个入参是const endpoint_type& peer_endpoint. 此处的类型 endpoint_type 是 ip::tcp::endpoint 在 在 ip::tcp::socket 类内部的一个别名。 libucurl 库采用字符串URL表达目标的地…

Android开机不显示bootloader界面

Turn it off in the following way LINUX\android\bootable\bootloader\edk2\QcomModulePkg\Library\BootLib\MenuKeysDetection.c 试了没有生效 --- a/QcomModulePkg/Library/BootLib/MenuKeysDetection.cb/QcomModulePkg/Library/BootLib/MenuKeysDetection.c-364,7 364,8…

显微测量|台阶仪二维超精密测量微观形貌

台阶仪通过扫描被测样品表面&#xff0c;获取高分辨率的表面形貌数据&#xff0c;能够揭示微观结构的特征和性能。 标题了解工作原理和性能特点 台阶仪利用扫描探针在样品表面上进行微观测量&#xff0c;通过探测探针和样品表面之间的相互作用力&#xff0c;获取表面形貌信息…

数据分析 — 动画图 pyecharts

目录 一、概念二、安装和导入三、绘图逻辑四、绘图1、柱状图2、折线图3、散点图4、饼图5、南丁格尔图6、Geo() 地理坐标第7、Map() 绘制区域8、词云图9、层叠图10、3D 图11、仪表板 一、概念 Pyecharts 是一个基于 Echarts 的 Python 可视化库&#xff0c;它通过 Python 生成 …

云计算基础-快照与克隆

快照及克隆 什么是快照 快照是数据存储的某一时刻的状态记录&#xff0c;也就是把虚拟机当前的状态保存下来(快照不是备份&#xff0c;快照保存的是状态&#xff0c;备份保存的是副本) 快照优点 速度快&#xff0c;占用空间小 快照工作原理 在了解快照原理前&#xff0c;…

WordPress主题YIA移动端文章页的面包屑不显示怎么办?

平时我们一般都会在文章页导航菜单下方显示面包屑&#xff0c;类似于“当前位置&#xff1a;boke112百科 WordPress 正文”。平时用浏览器调试站点的时候&#xff0c;在Edge浏览器的“切换设备仿真”中&#xff0c;不管是选择什么设备都会显示面包屑。具体如下图所示&#xf…

抓包分析 TCP 协议

TCP 协议是在传输层中&#xff0c;一种面向连接的、可靠的、基于字节流的传输层通信协议。 环境准备 对接口测试工具进行分类&#xff0c;可以如下几类&#xff1a; 网络嗅探工具&#xff1a;tcpdump&#xff0c;wireshark 代理工具&#xff1a;fiddler&#xff0c;charles&…

3分钟了解Android中稳定性测试

一、什么是Monkey Monkey在英文里的含义是猴子&#xff0c;在测试行业的学名叫“猴子测试”&#xff0c;指的是没有测试经验的人甚至是根本不懂计算机的人&#xff08;就像一只猴子&#xff09;&#xff0c;不需要知道程序的任何用户交互方面的知识&#xff0c;给他一个程序&a…

LeetCode刷题计划

LeetCode刷题计划 推荐 代码随想录&#xff1a;https://github.com/youngyangyang04/leetcode-master 卡码网 练习ACM模式 https://kamacoder.com/ 01 #include <iostream> using namespace std;int main() {int a ,b;while(cin>>a>>b){cout<<ab<…

基于51/STM32单片机的智能药盒 物联网定时吃药 药品分类

功能介绍 以51/STM32单片机作为主控系统&#xff1b; LCD1602液晶显示当前时间、温湿度、药品重量 3次吃药时间、药品类目和药品数量 HX711压力采集当前药品重量 红外感应当前药盒是否打开 DS1302时钟芯片显示当前年月日、时分秒、星期 DHT11采集当前环境温度和湿度 …

【presto权威指南】presto介绍

需求&#xff1a;如何从众多数据源中快速处理数据 现实生产架构多源异构&#xff0c;需要一个强有力的工具&#xff08;抽象&#xff09;统一数据查询/分析 这也是presto/trino从诞生之初便贴数据湖查询工具 tag的原因&#xff0c;presto生来为此 生产环境的困境 1.数据源众多…

无货源?想要1688平台货源,商品采集,第三方API来帮你实现

阿里巴巴(1688.com)批发网是全球企业间(B2B)电子商务的著名品牌&#xff0c;为天下网商提供海量商机信息和便捷安全的在线交易市场。从海量的商品中甄选热销新品、优质好商&#xff0c;为买家采购批发提供风向标。 不少做跨境电商无货源的朋友都想要直接从1688源头厂家拿货&am…

NOTA-马来酰亚胺,1295584-83-6,可作为过渡金属离子的配体

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;NOTA-马来酰亚胺&#xff0c;NOTA Maleimide &#xff0c;NOTA-Mal&#xff0c;1295584-83-6 一、基本信息 产品简介&#xff1a;NOTA Maleimide, also known as NOTA maleimide, is a novel bifunctional integrat…