美团点评2020校招前端方向笔试题

2,929 阅读6分钟

第一题

class A {
    String i = "op";
    void func(String s) {
        s = "" + 9;
    }
    static void test() {
        A a = new A();
        a.func(a.i);
    }
}

问: 1,变量i,s,a在堆还是栈中? 2,第8行执行完后a.i的值是什么?

点击查看答案
1,i, s, a都在栈中,new出来的对象A在堆上。(考察js堆与栈:栈内存主要用于存储各种基本类型的变量,包括Boolean、Number、String、Undefined、Null以及对象变量的指针,堆主要存储object,所以字符串变量i,s以及对象指针a都存在栈中,new出来的对象开辟内存存在堆上,对应地址是指针a存的内容)
2,执行完成后a.i的值还是字符串op。(考察参数传递按值传递:a是A类的实例,所以a.i='op',a.func(a.i)这句执行函数,把a.i作为参数传递,该函数会复制一个变量,两个变量完全独立,所以在函数体里只是把复制的那个变量(一个新的局部变量)改变为'op9’,在函数体外的a.i并没有被改变)

第二题

请按顺序写出打印结果,并说明原因。

var name = 'global';
var obj = {
    name: 'local',
    foo: function() {
        this.name = 'foo';
    }.bind(window)
};
var bar = new obj.foo();
setTimeout(function() {
    console.log(window.name);
}, 0);
console.log(bar.name);

var bar3 = bar2 = bar;
bar2.name = 'foo2';
console.log(bar3.name)
点击查看答案
foo-foo2-global
var bar = new obj.foo(); // 由于new绑定的优先级大于bind绑定,所以函数内部this还是obj{}
console.log(bar.name); // foo

// 此时执行顺序是var bar3,bar2=bar,bar3=bar2, 所以bar3/bar2/bar都是指向同一个对象 var bar3 = bar2 = bar; bar2.name = 'foo2'; // 所以bar2修改属性,bar3的也改变了,此时输出为'foo2' console.log(bar3.name);

// 定时器任务,在最后放入任务队列,window对象没有被改变,所以输出 'global' setTimeout(function() { console.log(window.name); }, 0);

第三题

请写出如下代码运行后产生的结果,并给出解释,说明结果是如何得出的。

setTimeout(() => console.log('a'))
Promise.resolve().then(
    () => console.log('b');
).then(
    () => Promise.resolve('c').then(
        (data) => {
            setTimeout(() => console.log('d'));
            console.log('f');
            return data;
        }
    )
).then(data => console.log(data))
点击查看答案
b->f->c->a->d
// 定时器任务属于宏任务,并且需要先在任务队列等待,等到同步任务执行完,执行栈清空,才会在任务队列中按顺序选任务进去
setTimeout(() => console.log('a'));//4. 打印a

//Promise 属于异步微任务,在本轮同步任务结束之前执行 Promise.resolve().then( // 1. 打印 b () => console.log('b') // 单引号要改为',然后去掉;号 ).then( // 箭头函数的resolve传递的参数作为下一个then的参数 () => Promise.resolve('c').then( // 执行箭头函数 (data) => { // 把定时器任务也放入任务队列中等待,在第一个定时器之后 setTimeout(() => console.log('d')); //5. 打印d // 2.打印 f console.log('f'); // 此时返回的 数据作为下一个then的参数 return data; } ) ).then(data => console.log(data)); // 3.打印 c

第四题

请写出下面ES6代码编译后所生成的ES5代码;

class Person {
    constructor(name) {
        this.name = name;
    }
    greet() {
        console.log(`Hi, my name is ${this.name}`);
    }
    greetDelay(time) {
        setTimeout(() => {
            console.log(`Hi, my name is ${this.name}`);
        }, time);
    }
}
点击查看答案

 var Person = (function () {
     function Person (name) {
          this._name = name;
     }
     Person.prototype.greet = function () {
          console.log(“Hi, my name is “ + this._name);
     }
     Person.prototype.greetDelay = function (time) {
          var _this = this;
          setTimeout(function () {
               console.log(“Hi, my name is “ + _this.name);
          }, time);
     }
})();
    

第五题

形如1, 1, 2, 3, 5, 8, 13, 21, 34, 55的数列,后一位是前面两位相加(斐波那契数列),写出函数要求找到第 N 位是多少,如:fib(3) => 3 , fib(5) => 8, 要求时间复杂度为O(n)。

输入描述:输入一个正整数N(0<=N<=50)
输出描述:输出第n项的数值
点击查看答案
var fib = function(N) {
    if(N==0)return 0;
    if(N==2||N==1)return 1;
    var prev=1,curr=1;
    for(var i=3;i<=N;i++){
        var sum=prev+curr;
        prev=curr;
        curr=sum;
    }
    return curr;
};

第六题

近期某商场由于周年庆,开启了“0元购”活动。活动中,消费者可以通过组合手中的代金券,实现0元购买指定商品。

聪明的小团想要用算法来帮助他快速计算:对于指定价格的商品,使用代金券凑出其价格即可,但所使用的代金券总面额不可超过商品价格。由于代金券数量有限,使用较少的代金券张数则可以实现价值最大化,即最佳优惠。

假设现有100元的商品,而代金券有50元、30元、20元、5元四种,则最佳优惠是两张50元面额的代金券;而如果现有65元的商品,则最佳优惠是两张30元代金券以及一张5元代金券。

请你帮助小团使用一段代码来实现代金券计算。

点击查看答案
var coinChange = function(coins, amount) {
    coins.sort((a, b) => b - a);
    let res = amount + 1;

    let dfs = function(index, cur, cnt) {
        let coins_i = coins[index];
        if (cnt + Math.ceil(cur / coins_i) >= res) return;

        if (cur % coins_i == 0) {
            res = cnt + Math.floor(cur / coins_i);
            return ;
        } 

        if (index == coins.length - 1) return ;

        for (let i = Math.floor(cur / coins_i); i >= 0; i--) 
            dfs(index + 1, cur - coins_i * i, cnt + i);
    }

    dfs(0, amount, 0);
    return res > amount ? -1 : res;
}

第七题

给定一个包含非负整数的 M x N 迷宫,请找出一条从左上角到右下角的路径,使得路径上的数字总和最小。每次只能向下或者向右移动一步。

点击查看答案
var minPathSum = function (grid) {
    // 时间复杂度和空间复杂度都是 O (m * n);
    if (grid.length === 0) return 0;
    const dp = [];
    const rows = grid.length;
    const cols = grid[0].length;
    // 实际上你也可以无差别全部填充为MAX_VALUE,对结果没影响,代码还会更少
    // 只是有点不专业而已
    for (let i = 0; i < rows + 1; i++) {
        dp[i] = [];
        // 初始化第一列
        dp[i][0] = Number.MAX_VALUE;
        for (let j = 0; j < cols + 1; j++) {
            // 初始化第一行
            if (i === 0) {
                dp[i][j] = Number.MAX_VALUE;
            }
        }
    }

    // tricky
    dp[0][1] = 0;

    for (let i = 1; i < rows + 1; i++) {
        for (let j = 1; j < cols + 1; j++) {
            // state transition
            dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
        }
    }

    return dp[rows][cols];
};

第八题

小团在一次星际旅行中,耗尽了飞船的能量,迷失在了空间魔方中,空间魔方中有NNN个能量粒子。美团云AI迅速帮小团分析出了空间魔方的能量分布图。

已知小团的飞船被困在能量值最高的点,能量值最高点有且只有一个。飞船每到达一个能量粒子就会吸收对应粒子的能量,该粒子会坍缩成小黑洞,飞船不可到达。小团驾驶的飞船只能从高能粒子驶向低能粒子,且每次只能从6个方向中选择一个前进。(±x,±y,±z)。

请帮助帮小团吸收最高的能量值。

点击查看答案 这题目前还没有解决

个人博客

前端常见面试题

LeetCode题JS解法