百度面试手撕代码:数组元素非自身乘积、异步队列、数组扁平化
刚面完百度一面,给了三道手撕代码,别家都是一道。不得不说,百度的面试在线编辑器是我用过最好用的,跟vscode一样。
题目一:数组元素非自身乘积
题目描述:
给定一个整数数组nums,返回一个数组answer,其中answer[i]等于nums中除nums[i]之外其余各元素的乘积。
要求:
- 不要使用除法,且在O(n)时间复杂度内完成。
解题思路: 为了在不使用除法的情况下计算每个元素的非自身乘积,我们可以维护两个数组,一个用于存储每个元素左边所有元素的乘积,另一个用于存储每个元素右边所有元素的乘积。最后,将这两个乘积相乘即可得到结果。
代码实现:
function productExceptSelf(nums) {
const n = nums.length;
const result = new Array(n).fill(1);
let leftProduct = 1;
for (let i = 0; i < n; i++) {
result[i] *= leftProduct;
leftProduct *= nums[i];
}
let rightProduct = 1;
for (let i = n - 1; i >= 0; i--) {
result[i] *= rightProduct;
rightProduct *= nums[i];
}
return result;
}
题目二:基于Promise的异步队列
题目描述: 基于Promise实现一个task queue,其中task可以链式调用,上一个任务执行完毕才执行下一个。
要求:
- task是一个用于存储异步任务的函数,可以链式调用,保证上一个任务执行完毕后才能执行下一个。
- run方法用于循环执行异步任务。
解题思路: 我们可以定义一个TaskQueue类,其中包含一个任务数组和一个currentPromise用于追踪当前执行的任务。每个任务可以是一个返回Promise的函数,通过链式调用添加到任务队列中。
代码实现:
class TaskQueue {
constructor() {
this.tasks = [];
this.currentPromise = Promise.resolve();
}
task(wait, callback) {
this.tasks.push({ wait, callback });
return this;
}
run() {
this.tasks.forEach(task => {
this.currentPromise = this.currentPromise.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
const result = task.callback();
if (result instanceof Promise) {
result.then(resolve).catch(reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}, task.wait || 0);
});
});
});
return this.currentPromise;
}
}
题目三:多维数组扁平化
题目描述: 将一个多维数组扁平化为一维数组。
解题思路:
多维数组的扁平化可以通过递归、reduce()方法、for...of循环或Array.prototype.flat()方法实现。
代码实现:
function flattenArray(arr) {
return arr.reduce((acc, item) => {
return acc.concat(Array.isArray(item) ? flattenArray(item) : item);
}, []);
}
const multiDimensionalArray = [1, [2, [3, [4]], 5]];
const flattenedArray = flattenArray(multiDimensionalArray);
console.log(flattenedArray); // 输出: [1, 2, 3, 4, 5]
总结
这三道题目覆盖了数组操作、异步编程和递归算法等多个方面,是技术面试中常见的手撕代码题目。