LeetCode JS专栏刷题笔记(一)

news2024/11/22 19:07:18

一、前言

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 = 0
    for(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.coloradmin.cn/o/1457927.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven(基础)、MyBatis

简介 Apache Maven是一个项目管理和构建工具&#xff0c;它基于项目对象模型 (POM)的概念&#xff0c;通过一小段描述信息来管理项目的构建、报告和文档 官网: http://maven.apache.org/ Maven作用 Maven是专门用于管理和构建Java项目的工具&#xff0c;它的主要功能有&#x…

Elasticsearch查询报错 Result window is too large

一现象&#xff1a; es数据分页查询前端提示系统异常&#xff0c;后端报错日志 二根本原因&#xff1a; 默认情况下&#xff0c;Elasticsearch 限制了 from size 参数的组合不能超过 10,000 条记录&#xff0c;用于防止查询大数据集时对系统资源的过度消耗 三解决办法&#…

JavaSE——面向对象基础(1/4)-面向对象编程、程序中的对象、对象的产生、对象的执行原理、类和对象的一些注意事项

目录 面向对象编程 程序中的对象 对象的产生 对象的执行原理 类和对象的一些注意事项 面向对象编程 开发一个一个的对象&#xff0c;把数据交给对象&#xff0c;再调用对象的方法来完成对数据的处理。 例如设计一个学生的对象&#xff0c;其中有姓名和成绩等&#xff0c…

可视化视频监控平台EasyCVR如何配置服务参数以免getbaseconfig接口信息泄露?

可视化云监控平台/安防视频监控系统EasyCVR视频综合管理平台&#xff0c;采用了开放式的网络结构&#xff0c;平台支持高清视频的接入和传输、分发&#xff0c;可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集…

【.NET Core】C#编程规范

【.NET Core】C#编程规范 文章目录 【.NET Core】C#编程规范一、概述1.1 结构清晰第一1.2 简洁之风1.3 代码风格保持一致性 二、命名约定三、类型参数命名指南3.1 请使用描述性名称命名泛型类型参数&#xff0c;除非单个字面名称完全具有自我说明性且描述性名称不会增加任何作用…

Redis(03)——发布订阅

基础命令 基于频道 publish channel message&#xff1a;将信号发送到指定的频道pubsub subcommand [argument [argyment]]&#xff1a;查看订阅或发布系统状态subscribe channel [channel]&#xff1a;订阅一个或多个频道的信息unsubscribe [channel [channel]]&#xff1a;退…

CSS:BFC

BFC&#xff0c;Block Formatting Context&#xff0c;块级格式化上下文&#xff0c;是一个独立的渲染区域或隔离的独立容器&#xff0c;它决定了其子元素如何布局&#xff0c;并且与这个区域外部的元素无关。 形成 BFC 的条件 float 的值不为 none&#xff08;left、right&a…

【Node.js和Appium server的下载安装步骤】

Node.js 是JavaScript的运行环境&#xff0c;是 JS 语言的解释器&#xff0c;之中集成了npm库。 npm 是世界上最大软件包仓库&#xff0c;可用于Appium server安装。 1、Node.js官方安装包及源码下载地址&#xff1a;Node.js 选择相应系统的安装包进行下载&#xff08;.msi用…

c编译器学习02:chibicc文档翻译

目的 先粗略地看一遍作者的书籍。 原文档地址 https://www.sigbus.info/compilerbook# “低レイヤを知りたい人のためのCコンパイラ作成入門” 为想了解底层的人准备的C编译器制作入门 Rui Ueyama ruiucs.stanford.edu 2020-03-16 作者简介 https://www.sigbus.info/ 植山…

知识蒸馏实战代码教学二(代码实战部分)

一、上章原理回顾 具体过程&#xff1a; &#xff08;1&#xff09;首先我们要先训练出较大模型既teacher模型。&#xff08;在图中没有出现&#xff09; &#xff08;2&#xff09;再对teacher模型进行蒸馏&#xff0c;此时我们已经有一个训练好的teacher模型&#xff0c;所以…

C++ 二分模版 数的范围

给定一个按照升序排列的长度为 n 的整数数组&#xff0c;以及 q 个查询。 对于每个查询&#xff0c;返回一个元素 k 的起始位置和终止位置&#xff08;位置从 0 开始计数&#xff09;。 如果数组中不存在该元素&#xff0c;则返回 -1 -1。 输入格式 第一行包含整数 n 和 q &…

QT串口通讯上位机_数据超时接收功能及定时发送功能设计

目录 1.概述2.本次内容最终实现3.代码部分4.完整工程文件下载 1.概述 基于《串口开发基础》 在该基础上增加超时时间接收功能&#xff0c;加入定时器循环&#xff1b; 例如&#xff0c;接收数据开始后&#xff0c;在100ms内未接收到任何数据&#xff0c;视作本次数据接收结束&…

数据结构第3章 串

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 本篇笔记整理&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 0、思维导图1、基本概念1&#xff09;主…

Java+SpringBoot:农业疾病防治新选择

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

NBlog个人博客部署维护过程记录 -- 后端springboot + 前端vue

项目是fork的Naccl大佬NBlog项目&#xff0c;页面做的相当漂亮&#xff0c;所以选择了这个。可以参考2.3的效果图 惭愧&#xff0c;工作两年了也没个自己的博客系统&#xff0c;趁着过年时间&#xff0c;开始搭建一下. NBlog原项目的github链接&#xff1a;Naccl/NBlog: &#…

leetcode(动态规划)53.最大子数组和(C++详细解释)DAY12

文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 提示 2.解答思…

Sora一出 哪里又要裁员了?

上班前夕迎来大新闻&#xff0c;那就是Sora了&#xff0c;Sora是什么&#xff0c;有什么牛逼之处&#xff0c;怎么实现的&#xff0c;我们跟着官方文档透露出来的一点点信息&#xff0c;简单的捋一捋。 一、Sora是什么 官方给出的定义是&#xff1a;世界模拟器。这很明显有夸大…

数据结构:动态内存分配+内存分区+宏+结构体

一、作业 1.定义一个学生结构体&#xff0c;包含结构体成员&#xff1a;身高&#xff0c;姓名&#xff0c;成绩&#xff1b;定义一个结构体数组有7个成员&#xff0c;要求终端输入结构体成员的值&#xff0c;根据学生成绩&#xff0c;进行冒泡排序。 #include <stdio.h>…

Qt C++春晚刘谦魔术约瑟夫环问题的模拟程序

什么是约瑟夫环问题&#xff1f; 约瑟夫问题是个有名的问题&#xff1a;N个人围成一圈&#xff0c;从第一个开始报数&#xff0c;第M个将被杀掉&#xff0c;最后剩下一个&#xff0c;其余人都将被杀掉。例如N6&#xff0c;M5&#xff0c;被杀掉的顺序是&#xff1a;5&#xff…

如何利用Idea创建一个Servlet项目(新手向)

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;如何利用Idea创建一个Servlet项目(新手向) Servlet是tomcat的api,利用Servlet进行webapp开发很方便,本文将介绍如何通过Idea创建一个Servlet项目(一共分为七步,这可能是我们写过的…