2021/03/04 欢聚时代面试笔试题| 刷题打卡

1,092 阅读3分钟

第一题:链式调用

题目: 实现一个如下的效果

People("神轻易").sayHello()
// output: 大家好我是神轻易
People("神轻易").sayHello().movement("我要宣布个事").wait(3).movement("我是伞兵");
// output:
// 大家好我是神轻易
// 我要宣布个事
// 休息3秒
// 我是伞兵
People("神轻易").sayHello().movement("我要宣布个事").wait(3).waitFirst(1).movement("我是伞兵");
// output:
// 休息1秒
// 大家好我是神轻易
// 我要宣布个事
// 休息3秒
// 我是伞兵

这题的考察重点在于js的事件循环、构造函数、原型链。

难点:

waitFirst()要实现后调用先执行,剩余函数按顺序执行,支持延时调用

思路:

要实现一个链式调用,有两种方法,构造函数或者Class,原理都一样,因为Class也可以看作是构造函数的语法糖。

说一下要点:

  • 建立一个事件队列
  • 每个方法都可以往事件队列推入一个事件,每个方法最终返回指向Function/Class本身,即this
  • waitFirst将插入队列头部
  • 顺序执行事件队列

可以看到,执行将放到最后进行。

解题代码:

构造函数:

function People(name) {
    this.tasks = []
    this.name = name
    setTimeout(()=>{
      this.then()
    })
}
People.prototype.sayHello=function(){
    this.tasks.push(()=>{
    	console.log(`大家好,我是${this.name}`)
    	this.then()
    })
    return this
  }
People.prototype.wait=function(time){
    this.tasks.push(()=>{
      console.log(`休息${time}秒`)
      setTimeout(()=>{
        this.then()
      },time*1000)
    })
    return this
  }
  People.prototype.waitFirst=function(time){
    this.tasks.unshift(()=>{
        console.log(`休息${time}秒`)
      setTimeout(()=>{
        this.then()
      },time*1000)
    })
    return this
  }
  People.prototype.movement=function(event){
    this.tasks.push(()=>{
      console.log(event)
      this.then()
    })
    return this
  }
  People.prototype.then=function(){
    const task = this.tasks.shift()
    task && task()
    return this
  }
new People("神轻易").sayHello().movement("我要宣布个事").wait(3).waitFirst(1).movement("我是伞兵");

Class:

class People {
  constructor(name){
    this.tasks = []
    this.name = name
    setTimeout(()=>{
      this.then()
    })
  }
  sayHello(){
    this.tasks.push(()=>{
    	console.log(`大家好,我是${this.name}`)
    	this.then()
    })
    return this
  }
  wait(time){
    this.tasks.push(()=>{
      console.log(`休息${time*1000}秒`)
      setTimeout(()=>{
        this.then()
      },time*1000)
    })
    return this
  }
  waitFirst(time){
    this.tasks.unshift(()=>{
        console.log(`休息${time*1000}秒`)
      setTimeout(()=>{
        this.then()
      },time*1000)
    })
    return this
  }
  movement(event){
    this.tasks.push(()=>{
      console.log(event)
      this.then()
    })
    return this
  }
  then(){
    const task = this.tasks.shift()
    task && task()
    return this
  }
}
new People("神轻易").sayHello().movement("我要宣布个事").wait(3).waitFirst(1).movement("我是伞兵");

分析:

为了分析得更细致,我改写一下,让大家看得更明白,实际上这段代码

new People("神轻易").sayHello().movement("我要宣布个事").wait(3).waitFirst(1).movement("我是伞兵");

等同于:

new People("神轻易");
People.sayHello();
People.movement("我要宣布个事");
People.wait(3);
People.waitFirst(1);
People.movement("我是伞兵");

在初始化该构造函数的时候,我们在这个函数上下文中依次添加了tasks数组,then方法,以及执行一个setTimeout()函数即:

  constructor(name){
    this.tasks = []
    this.name = name
    setTimeout(()=>{
      this.then()
    })
  }

我们知道,在js的事件循环中,有执行栈,同步任务会优先顺序执行,异步任务会被推入事件队列,分为微任务宏任务,待同步任务执行完成之后依次取出执行。所以在constructor中只有初始化tasks数组,以及name属性定义,setTimeout函数作为异步宏任务被挂起。

全部用同步方法表达,在这段构造函数内部,这句链式调用将是这样执行的:

// new People("神轻易").sayHello().movement("我要宣布个事").wait(3).waitFirst(1).movement("我是伞兵");
// 即:
this.tasks = []
this.name = '神轻易'

// 此时People:{name:'神轻易',tasks:[],then:...},setTimeout函数是宏任务,被挂起并继续执行后面的函数,即People.sayHello()

this.tasks.push(()=>{
    console.log(`大家好,我是${this.name}`)
    this.then()
})

// 此时People:{
//	name:'神轻易',
//	tasks:[()=>{
//		console.log(`大家好,我是${this.name}`)
//		this.then()
//	},],
//	then:...
// }
// 随后执行People.movement('我要宣布个事')

this.tasks.push(()=>{
    console.log(`大家好,我是${this.name}`)
    this.then()
})
//...将所有事件依次在队尾插入tasks中,注意waitFirst是插入队头

// 最后执行那个被挂起的宏任务setTimeout,而此时我们的tasks队列已经按照正确的顺序组合好了,只需要等待事件依次执行即可

第二题:股票问题

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/be… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

具体啥题忘了,反正原题是这个,一开始看错题了以为只能一次交易,后来面试官提醒我才反应过来原来是可以多次交易的但时间过了,就说了一下解题思路。

这个应该比较简单,直接贴代码吧,不限交易次数的话,今天比昨天价高就是利润。

function maxProfit(prices) {
  let profit = 0;
  for (let i = 1; i < prices.length; i++) {
    if (prices[i] - prices[i - 1] > 0) {
      profit += prices[i] - prices[i - 1];
    }
  }
  return profit;
}

下期预告:UC笔试题