百度 手撕 面经
二叉树最远节点的距离(二叉树的直径)
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
var diameterOfBinaryTree = function(root) {
let maxDiameter = 0;
function dfs(node) {
if (!node) return 0;
let leftDepth = dfs(node.left);
let rightDepth = dfs(node.right);
// 更新最大直径
maxDiameter = Math.max(maxDiameter, leftDepth + rightDepth);
// 返回节点的最大深度
return 1 + Math.max(leftDepth, rightDepth);
}
dfs(root);
return maxDiameter;
};
// 示例
let root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
console.log(diameterOfBinaryTree(root)); // 输出应为 3 (节点4 -> 2 -> 5的路径)
统计出现两次的元素
function findDuplicates(arr) {
let count = {}
let newArr = []
arr.forEach(item=>{
// count[item] = (count[item]||0)+1
if(count[item]){
count[item]++
}else{
count[item] = 1
}
})
for(let item in count){
if(count[item] === 2){
newArr.push(parseInt(item))
}
}
return newArr
}
// 示例用法
console.log(findDuplicates([1, 2, 2, 3, 4, 5, 5, 6])); // 输出: [2, 5]
手撕解析URL参数
function parseUrlParams(url) {
const queryString = url.split('?')[1];
const params = queryString.split('&');
const result = {};
params.forEach(param => {
const [key, value] = param.split('=');
result[key] = decodeURIComponent(value);
});
return result;
}
// 示例用法
console.log(parseUrlParams('http://example.com?page=3&limit=10&query=hello%20world'));
// 输出: { page: '3', limit: '10', query: 'hello world' }
合并区间
function mergeIntervals(intervals) {
if (!intervals.length) return intervals;
intervals.sort((a, b) => a[0] - b[0]);
const result = [intervals[0]];
for (let i = 1; i < intervals.length; i++) {
const prev = result[result.length - 1];
const current = intervals[i];
if (current[0] <= prev[1]) {
prev[1] = Math.max(prev[1], current[1]);
} else {
result.push(current);
}
}
return result;
}
// 使用示例
console.log(mergeIntervals([[1, 3], [2, 6], [8, 10], [15, 18]]));
// 输出: [[1, 6], [8, 10], [15, 18]]
反转字符串
function reverseString(str) {
return str.split('').reverse().join('');
}
console.log(reverseString('hello')); // 'ollelo'
全排列
function permute(arr) {
const result = [];
function backtrack(path, options) {
if (path.length === arr.length) {
result.push([...path]);
return;
}
for (let i = 0; i < options.length; i++) {
path.push(options[i]);
backtrack(path, options.slice(0, i).concat(options.slice(i + 1)));
path.pop();
}
}
backtrack([], arr);
return result;
}
console.log(permute([1, 2, 3]));
手写Promise
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value);
}
if (this.state === 'rejected') {
onRejected(this.reason);
}
if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => onFulfilled(this.value));
this.onRejectedCallbacks.push(() => onRejected(this.reason));
}
}
}
// 使用
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Success!');
}, 1000);
});
promise.then(value => {
console.log(value); // 'Success!'
}, reason => {
console.error(reason);
});
fetch-promise
function myFetchWithTimeout(url, options, timeout = 5000) {
// 创建 fetch 请求的 Promise
const fetchPromise = new Promise((resolve, reject) => {
fetch(url, options)
.then(response => {
if (response.ok) {
resolve(response);
} else {
reject(new Error('Fetch error: ' + response.statusText));
}
})
.catch(error => reject(new Error('Network error: ' + error.message)));
});
// 创建超时的 Promise
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Fetch timeout')), timeout);
});
// 使用 Promise.race 执行两个 Promise
return Promise.race([fetchPromise, timeoutPromise]);
}
// 使用示例
myFetchWithTimeout('https://jsonplaceholder.typicode.com/todos/1', {}, 3000)
.then(response => response.json())
.then(data => console.log('Fetch success:', data))
.catch(error => console.error('Fetch error:', error));
数组去重
//使用 Set
const uniqueArray = arr => [...new Set(arr)];
console.log(uniqueArray([1, 2, 2, 3])); // [1, 2, 3]
//使用 filter 和 indexOf
const uniqueArray = arr => arr.filter((item, index) => arr.indexOf(item) === index);
console.log(uniqueArray([1, 2, 2, 3])); // [1, 2, 3]
//使用 reduce
const uniqueArray = arr => arr.reduce((acc, item) => {
if (!acc.includes(item)) acc.push(item);
return acc;
}, []);
console.log(uniqueArray([1, 2, 2, 3])); // [1, 2, 3]
函数柯里化
将一个多参数函数转换为一系列单参数函数的过程
function curry(fn) {
const arity = fn.length;
return function curried(...args) {
if (args.length >= arity) {
return fn(...args);
} else {
return function(...nextArgs) {
return curried(...args, ...nextArgs);
};
}
};
}
// 使用示例
function add(a, b, c) {
return a + b + c;
}
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6
实现 add(1, 2, 3) === add(1)(2)(3)
function add(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
console.log(add(1, 2, 3) === add(1)(2)(3)); // true
手写 new
new 操作符执行以下步骤:
- 创建一个新对象。
- 将构造函数的
prototype赋值给新对象的__proto__。 - 执行构造函数,将
this绑定到新对象。 - 如果构造函数返回一个对象,则返回该对象,否则返回新对象。
function myNew(constructor, ...args) {
const obj = {};
Object.setPrototypeOf(obj, constructor.prototype);
const result = constructor.apply(obj, args);
return result !== null && (typeof result === 'object' || typeof result === 'function') ? result : obj;
}
// 使用示例
function Person(name) {
this.name = name;
}
const person = myNew(Person, 'John');
console.log(person.name); // John
二叉树前序遍历
function preOrderTraversal(root) {
const result = [];
function traverse(node) {
if (!node) return;
result.push(node.value);
traverse(node.left);
traverse(node.right);
}
traverse(root);
return result;
}