前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试官:你能回答这两个简单的问题吗

面试官:你能回答这两个简单的问题吗

原创
作者头像
PHP开发工程师
发布2022-05-20 09:58:58
2670
发布2022-05-20 09:58:58
举报
文章被收录于专栏:thinkphp+vue

背景

这是我的朋友在最近一次面试中被问到的两个问题,来一起学习一下。

1. 如何防止重复发送多个请求?

问题:

在我们的工作中,经常需要只发送一次请求,以防止用户重复点击。

请编写请求方法(执行后返回 promise)并返回一个新方法。当连续触发时,将只发送一个请求。

事例

代码语言:javascript
复制
function firstPromise () {
  // ...Please fill in here
}
let count = 1;
let promiseFunction = () =>
  new Promise(rs =>
    window.setTimeout(() => {
      rs(count++)
    })
  )
let firstFn = firstPromise(promiseFunction)
firstFn().then(console.log) // 1
firstFn().then(console.log) // 1
firstFn().then(console.log) // 1
复制代码

问题分析

与算法问题相比,这个问题相对简单,我们只需要使用闭包和 Promise 的特征就可以完成。

代码语言:javascript
复制
function firstPromise(promiseFunction) {
  // Cache request instance
  let p = null
  return function (...args) {
    // 如果请求的实例已经存在,说明请求正在进行中,
    // 直接返回该实例,而不触发新的请求。
    return p
      ? p
      // 否则就发送该请求,并在Promise结束时将p设置为null,然后可以重新发送下一个请求
      : (p = promiseFunction.apply(this, args).finally(() => (p = null)))
  }
}
复制代码

测试

代码语言:javascript
复制
let count = 1
let promiseFunction = () =>
  new Promise((rs) =>
    setTimeout(() => {
      rs(count++)
    }, 1000)
  )
let firstFn = firstPromise(promiseFunction)
firstFn().then(console.log) // 1
firstFn().then(console.log) // 1
firstFn().then(console.log) // 1
setTimeout(() => {
  firstFn().then(console.log) // 2
  firstFn().then(console.log) // 2
  firstFn().then(console.log) // 2
}, 3000)
复制代码

2. 两数之和

这是力扣的第 1 题,请看这里:leetcode.cn/problems/tw…

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

  示例 1:

代码语言:javascript
复制
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
复制代码

示例 2:

代码语言:javascript
复制
输入:nums = [3,2,4], target = 6
输出:[1,2]
复制代码

示例 3:

代码语言:javascript
复制
输入:nums = [3,3], target = 6
输出:[0,1]
复制代码

方法一:使用两层 for 循环

我们最快想到的方式就是暴力破解,直接用 for 鲁,如下:

代码语言:javascript
复制
const twoSum = (nums, target) => {
  const len = nums.length
  for (let i = 0; i < len; i++) {
    for (let j = i + 1; j < len ; j++) {
      // find the answer, return
      if (nums[ i] + nums[ j ] === target) {
        return [ i, j ]
      }
    }
  }
}
复制代码

面试官表扬了她的快速回答,但他对结果并不满意,他认为有进一步优化的可能。

方法 2:使用 Map

通常,当使用两个 for 循环来求解一个问题时,我们需要意识到算法的时间复杂度 **(o (n2))** 是可以优化的。

事实上,我们可以用一个 "for" 循环来做,只要把加法变成减法,并且把遍历的值储存在一个对象 sumCache 中。

例如:

输入: [2,7,11,15]

步骤 1:

  1. 读取 2, 此时 sumCache 为空。
  2. sumCache 中存储 2 作为键,索引 0 作为值。

步骤 2:

  1. 7,发现目标值是 9-7 = 2。
  2. 2 存在于 sumCache 中,0 和 1 的索引将被直接返回。

你认为使用 Map 的方法是否简单明了,比 for 循环容易得多?

这很好。我们得到了更好的结果。我们只多用了 1.5M 的空间,时间减少了近一半。

源码附件已经打包好上传到百度云了,大家自行下载即可~

代码语言:javascript
复制
链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27
提取码: yu27

百度云链接不稳定,随时可能会失效,大家抓紧保存哈。

如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~

开源地址

码云地址: http://github.crmeb.net/u/defu

Github 地址: http://github.crmeb.net/u/defu

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 1. 如何防止重复发送多个请求?
  • 2. 两数之和
    • 方法一:使用两层 for 循环
      • 方法 2:使用 Map
      • 开源地址
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档