面试官:还能优化吗? 还有其他解法吗?

212 阅读4分钟

前言

众所周知,面试官总是喜欢在算法题和编程题上刨根问底,听到还能优化吗?还有其他解法吗?兄弟们头都是大的,可没办法啊,只能硬着头皮上了,不然答对了也不算满分。今天给大家分享两道面试官喜欢问的两道题。

1. 求x的n次方

听到这道题,我心里想着:“这也太简单了,没难度啊。”

{A2230D53-B674-4AB5-8E27-17A19DA8CB4B}.png

function fun1(x,n){
    let result = 1;
    for(let i = 0; i<n; i++) {
        result*=x;
    }
    return result;
}

于是我轻轻松松写出一个函数,通过一个循环将将 x 乘以自身 n 次,最终得到结果。

结果面试官问:“还有吗?”

我心想:“就知道你还有这一手,我特意留了个递归的方法没说。”

{42672650-AE58-473E-90AD-96EC9CD293C8}.png

function fun1(x,n){
    // 退出条件
    if(n === 0) {
        return 1;
    }else {
        return x * fun1(x, n - 1);
    }
}

于是我又轻轻松松的写出来了,通过递归不断调用自身,得出结果。

我心想:“这下你没话说了吧,赶快开始下一题吧。”

结果面试官又问:“你这两个方法有啥区别啊,时间复杂度都是O(n),还能优化一下吗?”

这可苦了我了,我左思右想也想不出一个好的解决办法,实在没办法了,我只能对面试官说:“不好意思,老师,我实在没有思路,能稍微提醒一下吗?”

{31EDBF0B-C87A-4C71-9F12-C4DEEF9433E2}.png

面试官看着我叹了一口气,说:“x的n次方 等于 x的二分之n次方 乘以 自己本身。”

这一下,我豁然开朗,只要通过将 n 减半并根据 n 的奇偶性来进行不同的计算就可以得到结果了。

function fun1(x,n) {
    if(n === 0) {
        return 1;    
    }
    let t = fun1(x, Math.floor(n / 2));
    if(n % 2 === 1) {
        return t * t * x; // 奇数 t * t * x
    }else {
        return t * t;// 偶数 t * t
    }
}

通过这种思路一下就避免了简单递归中出现的大量重复计算,将时间复杂度优化到了O(log2 n)。

2. 类数组

“你了解类数组吗?”面试官如此问道。

我斟酌了一下语言,说道:“类数组就是那些不是 Array 对象,但是具有一些类似数组的属性和方法的对象。”

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>类数组</title>
</head>
<body>
  <p>这是第1个段落</p>
  <p>这是第2个段落</p>
  <p>这是第3个段落</p>
  <p>这是第4个段落</p>
  <p>这是第5个段落</p>
  <p>这是第6个段落</p>
  <p>这是第7个段落</p>
  <p>这是第8个段落</p>
  <p>这是第9个段落</p>
  <p>这是第10个段落</p>
  <script>
    const nodeArr = document.getElementsByTagName('p');
    const nodeList = document.querySelectorAll('p');
    console.log(nodeArr,nodeList);
    nodeList.join(',')
  </script>
</body>
</html>

“这段代码中 nodeArrnodeList 有什么区别。”面试官问。

我:“它们通过 DOM 方法返回的分别是 HTMLCollection 和 NodeList ,虽然它们都是类数组,但它们的属性不同。例如......”

面试官:“不错,那请问 nodeList.join(',') 这段代码运行结果是什么”

我:“emm,因为数组和类数组的内置的方法不同,所以大概率会报错吧。”

面试官:“不错,那请问它们为什么属性和方法会不同呢,数组与类数组,类数组与类数组,它们的属性和方法是从哪来的呢。”

面对面试官的步步逼近。我有点招架不住,不知如何表达,心想:“学校没教啊!”

我突然灵机一动,在JavaScript中,管你什么数组,类数组都是对象,既然是对象那就有原型,而原型上的属性和方法是可以继承的,它们属性和方法不同的原因应该就是原型不同。

我答道:“数组和类数组的属性不同的主要原因是它们指向的原型不同,原型都不同,继承下来的属性和方法肯定也不同,类数组也是如此,尽管都叫类数组,但 HTMLCollection指向的原型是 HTMLCollection.prototype ,而 NodeList 指向的是 NodeList.prototype 。它们的原型其实也不相同。

面试官:“非常不错,那如果我想得到的这些类数组具体的属性和方法该怎么办呢?”

想通了后,这些都是简单的问题。

我:“只需在控制台输入 nodeList.__proto__ 就可以看到所有的属性和方法了。”

{7E81A818-B4EF-4B67-9BD4-123D67F658A0}.png

结语

面对面试官的死缠烂打,千万不要轻言放弃,实在不会了可以腆着脸皮问问面试官,毕竟算法题中总有一道是很难的,对于这种有难度的题,他不仅考察你的逻辑能力,代码能力,还会考察你的学习能力和社交能力。希望这篇文章能给你带来帮助,我们一起进步,顶峰相见!!