LeetCode JS专栏刷题笔记(二)

一、前言

LeetCode - JavaScript 专栏刷题笔记第二篇。

第一篇刷题笔记详见:LeetCode JS专栏刷题笔记(一)

二、算法题目

1. 复合函数

LeetCode地址:2629. 复合函数

请你编写一个函数,它接收一个函数数组 [f1, f2, f3,…, fn] ,并返回一个新的函数 fn ,它是函数数组的 复合函数

[f(x), g(x), h(x)]复合函数fn(x) = f(g(h(x)))

一个空函数列表的 复合函数恒等函数 f(x) = x

你可以假设数组中的每个函数接受一个整型参数作为输入,并返回一个整型作为输出。

Pasted image 20230709114449.png

思路

这道题并不难,但是有一个用的比较少的 API 可以直接实现,所以拿出来讲一讲。

这道题乍一看有点难以理解,实际就是给你一个初始值 x, 然后从右至左依次执行。

那么我们从数组末尾往前遍历,每次将最新的值更新到 x ,用于下次执行传入即可。

类似 Array#reduce 的 API 是 Array#reduceRight 。与 reduce 的遍历顺序相反,是从右至左累计和 的一个 API ,这道题可以直接使用 reduceRight 解决。

具体实现

方法一:遍历
/**
 * @param {Function[]} functions
 * @return {Function}
 */
var compose = function(functions) {
    return function(x) {
      for(let i = functions.length - 1; i >= 0; i--) {
          x = functions[i](x)
      }
      return x;
    }
};
方法二:reduceRight
/**
 * @param {Function[]} functions
 * @return {Function}
 */
var compose = function(functions) {
	return function(x) {
      return functions.reduceRight((total, fn) => fn(total), x);
    }
};

2. 分组

LeetCode地址:2631. 分组

请你编写一段可应用于所有数组的代码,使任何数组调用 array.groupBy(fn) 方法时,它返回对该数组 分组后 的结果。

数组 分组 是一个对象,其中的每个键都是 fn(arr[i]) 的输出的一个数组,该数组中含有原数组中具有该键的所有项。

提供的回调函数 fn 将接受数组中的项并返回一个字符串类型的键。

每个值列表的顺序应该与元素在数组中出现的顺序相同。任何顺序的键都是可以接受的。

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

Pasted image 20230709115302.png

思路

比较初级的题,实际开发中会遇到类似功能比较多,仅仅考察了一下哈希表的使用。

这道题的要求是,根据传入的 fn 函数的结果进行分组,图中示例给的已经很清楚了,不在多解释。

我们直接根据 fn(item) 的不同结果的存入数组就可以了。

具体实现

/**
 * @param {Function} fn
 * @return {Array}
 */
Array.prototype.groupBy = function(fn) {
    const map = {};
    this.forEach( item =>{
      const key = fn(item);
      if(!map[key]) {
          map[key] = [item];
      }else{
          map[key].push(item)
      }
    })
	return map
};

/**
 * [1,2,3].groupBy(String) // {"1":[1],"2":[2],"3":[3]}
 */

3. 柯里化

LeetCode地址:2632. 柯里化

请你编写一个函数,它接收一个其他的函数,并返回该函数的 柯里化 后的形式。

柯里化 函数的定义是接受与原函数相同数量或更少数量的参数,并返回另一个 柯里化 后的函数或与原函数相同的值。

实际上,当你调用原函数,如 sum(1,2,3) 时,它将调用 柯里化 函数的某个形式,如 csum(1)(2)(3)csum(1)(2,3)csum(1,2)(3),或 csum(1,2,3) 。所有调用 柯里化 函数的方法都应该返回与原始函数相同的值。

Pasted image 20230709115514.png

思路

柯里化是一种关于函数的高阶技术,他不仅被用于 Javascript,还被用于其他编程语言。

柯里化可以将一个函数从可调用的 sum(1,2,3) 转换成可调用的 f(1)(2)(3)

也就是说:柯里化将原本一个一次性接受多参数的函数,转换为多次接受部分参数的函数,这种转换过程涉及到将原始函数的参数拆分为多个部分,并返回一个新的函数,每次接受一些参数,直到接受完所有参数并执行原始函数。

实现该方法的关键点是一个不常用的属性:fn.length , 在 JS 中 函数自带的 length 属性返回的该函数的参数个数。

解释完 柯里化 的作用及关键的 fn.length 属性,想实现就不难了。

既然柯里化是需要等到接受完所有的参数再返回结果,那么我们维护一个数组,将每次传入的参数存入数组中,直到 参数各数 === fn.length 再将 fn(参数列表) 的执行结果返回即可。

具体实现

/**
 * @param {Function} fn
 * @return {Function}
 */
var curry = function(fn) {
    // 缓存已经传入的参数列表
    const argList = [];
    return function curried(...args) {
      argList.push(...args);
      // 判断参数个数是否满足要求
      if(argList.length === fn.length) {
        return fn(...argList);
      }
      // 不满足要求再次返回柯里化函数
      return curried;
    };
};

/**
 * function sum(a, b) { return a + b; }
 * const csum = curry(sum);
 * csum(1)(2) // 3
 */

4. 将对象转换为 JSON 字符串

LeetCode地址:2633. 将对象转换为 JSON 字符串

现给定一个对象,返回该对象的有效 JSON 字符串。你可以假设这个对象只包括字符串、整数、数组、对象、布尔值和 null。返回的字符串不能包含额外的空格。键的返回顺序应该与 Object.keys() 的顺序相同。

请你在不使用内置方法 JSON.stringify 的前提下解决这个问题。

Pasted image 20230709115720.png

思路

前端基本功:手写 JSON.stringify

手写简化版的 JSON.stringify 并不难,只要将题目要求中的几个不同类型的数据考虑到,分类处理好即可。

根据题目要求,转换成 JSON 字符串有主要有 5 类不同的数据需要分别判断

  • null 值: 需要手动转换成 null 字符串,否则会在处理数组或对象中遇到会直接成为空,同时 null 会被判定为 object 类型。
  • 字符串类型:字符串需要手动拼接 \", 否则在拼接字符串时不会保留双引号
  • 基本类型:如 boolean, number 直接保持原值即可。
  • 数组:考虑到数组中可能包含对象、数组,所以需要递归遍历每一项处理好后进行拼接
  • 对象:同样,也需要考虑对象中包含数组及对象,也需要进行递归处理

为了简化拼接字符串的代码量,我们直接通过模板字符串进行拼接即可。

具体实现

/**
 * @param {any} object
 * @return {string}
 */
var jsonStringify = function(object) {
    // 处理 null 值
    if(object === null) return "null"
    // 处理基本类型
    if(typeof object !== 'object') {
        return typeof object === 'string' ?  `\"${object}\"` : object;
    }
    // 处理数组类型
    if(Array.isArray(object)) {
        return `[${object.map(jsonStringify)}]`
    }
    // 处理对象类型
    return `{${Object.keys(object).map((key)=> `\"${key}\":${jsonStringify(object[key])}`)}}`
};

5. 两个对象之间的差异

LeetCode地址:2700. 两个对象之间的差异

请你编写一个函数,它接收两个深度嵌套的对象或数组 obj1obj2 ,并返回一个新对象表示它们之间差异。

该函数应该比较这两个对象的属性,并识别任何变化。返回的对象应仅包含从 obj1obj2 的值不同的键。对于每个变化的键,值应表示为一个数组 [obj1 value, obj2 value] 。不存在于一个对象中但存在于另一个对象中的键不应包含在返回的对象中。在比较两个数组时,数组的索引被视为它们的键。最终结果应是一个深度嵌套的对象,其中每个叶子的值都是一个差异数组。

你可以假设这两个对象都是 JSON.parse 的输出结果。

Pasted image 20230712211445.png

思路

该题要求比对两个对象,并将原值与修改后的值作为一个数组返回,如果是新增或者删除的属性,直接忽略不做处理。

假设有以下两个对象:

o1 = { a: 1, b: 2}
o2 = { a: 3, b: 2}

我们根据上面两个对象可以比对出属性 a 发生了变化,那么我们返回 {a:[1, 3]} 即可。

处理 JSON 的题,基本类似,无非考察递归的掌握与数据类型的控制,我们根据一下几个特征进行判断即可。

  • 如果 obj1 和 obj2 不是同一类型,直接返回 [obj1,obj2]
  • 如果 obj1 和 obj2 是都是基本类型时,直接判断结果,如果不一致则返回[obj1, obj2]
  • 如果 二者都是引用类型,则调用 objDiff(obj1[key], obj2[key]) 递归校验。

具体实现

/**
 * @param {object} obj1
 * @param {object} obj2
 * @return {object}
 */
function objDiff(obj1, obj2) {
  // 如果 key 已经被删除,不做处理
  if(obj2 === void 0) return void 0;
  // 如果是基本类型,或者两个对象的类型不一样,则直接返回比对后的结果
  // 注:对象类型不一样,值一定不一样
  if(typeof obj1 !== 'object' || obj1 === null || isNotEqualsType(obj1, obj2)) {
    return obj1 === obj2 ? void 0 : [ obj1, obj2 ];
  }
  // 保存比对后的结果
  const diffMap = {};
  for(const key of Object.keys(obj1)){
    // 递归比对当前 key 是否一致
    const diff = objDiff(obj1[key], obj2[key]);
    // 如果是 undefined 或者 对象是空的,则说明对象是一致的
    if(diff !== void 0 && Object.keys(diff).length) {
      diffMap[key] = diff;
    }
  }
  return diffMap;
};
const getType = (val) => Object.prototype.toString.apply(val);
const isNotEqualsType = (val1 , val2) => getType(val1) !== getType(val2); 

三、结语

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(2024,自级联扩散,关键点引导的噪声重新调度,时间感知特征上采样器)进行廉价的扩展:用于更高分辨率适应的自级联扩散模型

Make a Cheap Scaling: A Self-Cascade Diffusion Model for Higher-Resolution Adaptation 公和众和号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0. 摘要 2. 相关工作 4. 自级联扩散模型 …

【数据结构与算法】手搓JDK底层ArrayList底层 - 动态数组

数组 在介绍数组之前,我们先来看一段chatGPT给出的对于数组描述: 数组(Array)是一种线性数据结构,它由一组连续的内存空间组成,用来存储相同类型的数据元素。数组具有固定的大小,一旦创建后&a…

【Docker】前后端分离项目 Gin+Vue 容器化部署 | docker-compose 部署 | 部署 nginx 通过域名访问

文章目录 前言前后端不完全独立docker 部署mysqlredisrbac docker compose 部署部署 nginx 前后端独立部署 前言 项目地址:https://gitee.com/Cauchy_AQ/rbac 项目前端使用 vue3 并且由 vite 构建,后端采用 gin 框架,搭建了一个简易的权限管…

计算机设计大赛 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 DeepSORT车辆跟踪3.1 Deep SORT多目标跟踪算法3.2 算法流程 4 YOLOV5算法4.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 *…

WildCard:一个因太好用而被迫暂停服务的虚拟信用卡平台,魅力何在?

如果你需要使用Wildcard开通GPT4、Midjourney或是Only方式的话,请点击:WildCard使用教程 参考文章链接:WildCard:一个因太好用而被迫暂停服务的虚拟信用卡平台,魅力何在? 1、Wildcard用户数量激增&#x…

lombok的Getter, Setter报错 cannot find symbol

今天突然发现项目里的lombok失效了,get , set全部报错 java: cannot find symbol 觉得很奇怪,年前放假前都好好的,没改过代码,依赖,注解都正确,突然报这个错。 后来才发现是因为重装过系统,id…

机器人十大前沿技术(2023-2024年)

2023-2024年机器人十大前沿技术 1. 具身智能与垂直大模型 具身智能是指拥有自主感知、交互和行动能力的智能体,能够与环境进行实时互动,从而实现对环境的理解和适应。 “大模型”是指在深度学习和人工智能领域中,使用大量参数和数据进行训…

【Visual Studio】技巧 :自动与活动文档同步

在这里插入图片描述 工具 -> 选项 -> 项目和解决方案 - 勾选上面的 我厉害不!!!

php基础学习之常用系统函数

一,有关输出的语句/函数 echo语句 用于输出一个或多个字符串 print语句 用于输出一个字符串(用句点连接的多个字符串本质是一个字符串),与echo类似,但返回值为1 printf()函数 用于格式化输出字符串,类似于C…

东方博宜 1395. 小丽找数?

东方博宜 1395. 小丽找数&#xff1f; #include<iostream> using namespace std; int main() {int x ;cin >> x ;int cnt 0 ;for (int i 1 ; i < x ; i){ int y i ;int sum 0;while(y > 0){sum y%10 ;y / 10 ;}if(sum%5!0 &&sum%2!0)cnt 1 …

莱卡云怎么样?简单测评下莱卡云韩国CN2云服务器

莱卡云服务器厂商&#xff0c;国内持证企业服务器商家&#xff0c;运作着香港、美国、韩国、镇江、日本、绍兴、枣庄、等数据中心的云服务器、独立服务器出租、设备托管、CDN等业务。今天为大家带来的是莱卡云韩国CN2服务器的详细评测&#xff0c;该云服务器的数据中心位于韩国…

网络同步—帧同步和状态同步解析

概述 同步就是要多个客户端表现效果是一致的&#xff0c;而且对于大多数的游戏&#xff0c;不仅仅要表现一致&#xff0c;还要客户端和服务器的数据也是一致的。所以同步是个网络游戏概念&#xff0c;只有网络游戏才需要同步&#xff0c;而单机游戏是不需要同步的。 帧同步和…

在vscode中使用正则表达式删除python的注释

出于一些原因&#xff0c;需要删除所有的注释 vscode中用全文搜索替换的功能 点击红色按钮即可使用正则表达式。 1. 多行注释 [|"][|"][|"](.*\n)*?.*[|"][|"][|"] 里面主要需要注意的就是不要使用贪婪匹配&#xff0c;也就是 *? 的?这里…

并查集,真好用,一次AC不是梦!

文章目录 &#x1f680;前言&#x1f680;并查集&#x1f680;并查集的两个优化✈️路径压缩✈️按秩合并 &#x1f680;并查集代码模板 &#x1f680;前言 大家好啊&#xff01;今天阿辉来给大家介绍一种简洁而优雅的数据结构——并查集&#xff0c;不知道各位是否了解它&…

Paper Digest | 突破个性化推荐数据稀疏性:长尾增强的图对比学习算法研究

00 导读 本文将介绍的论文 Long-tail Augmented Graph Contrastive Learning for Recommendation 已被 ECML/PKDD 2023 Research Track 接收。 论文链接&#xff1a;https://arxiv.org/abs/2309.11177 论文中提到的模型实现&#xff0c;已经完全复现到 OpenAGL 里了&#xff…

186205-33-4,Cyanine2活化酯,可标记各种纳米材料和生物样品

186205-33-4&#xff0c;Cyanine2 NHS Ester&#xff0c;Cy2 NHS&#xff0c;Cy2活化酯&#xff0c;Cyanine2活化酯&#xff0c;可标记各种纳米材料和生物样品 您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;186205-33-4&#xff0c;Cyanine2 NHS Ester&#xff0…

基于 Reactive Mode 的 Flink 自动扩容

翻译自 Apache Flink: Scaling Flink automatically with Reactive Mode 简介 流式作业长时间运行过程中常常会经历不同流量负载的情况。流量负载会出现周期性的变化&#xff0c;如&#xff1a;白天与晚上、周末与工作日、节假日与非节假日&#xff0c;这些波动可能是突发事件…

消息队列(Message Queue)

目录 一、概念 二、消息队列使用场景 1.应用解耦&#xff1a;将应用进行解耦 具体场景&#xff1a;用户下单后&#xff0c;订单系统需要通知库存系统 2.异步处理&#xff1a;多应用对消息队列中同一消息进行处理&#xff0c;应用间并发处理消息&#xff0c;相比串行处理&…

当excel中表格打印预览右边超出限定页面时,调整列宽

解决办法&#xff1a;调整整体列或者部分列的列宽 操作流程如下&#xff1a; 第一步&#xff1a;选中需要调整的列 ①将鼠标放在表格的列上&#xff0c;等出现向下粗箭头后——>②单击&#xff08;变成粗十字&#xff09;该列——>③拖动选中列 第二步&#xff1a;调…

无人机技术,无人机动力系统知识,电机、电调、桨叶技术详解

无人机动力系统中的电机、电调和桨叶技术都是非常重要的部分&#xff0c;以下是对这些技术的详解&#xff1a; 无人机电机 在无人机动力系统中&#xff0c;电机是将电能转化为机械能的关键部件。其主要作用是产生旋转力矩&#xff0c;驱动螺旋桨的旋转&#xff0c;从而实现无…