1、深拷贝
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj; // 如果是基本类型或null,则直接返回
}
if (Array.isArray(obj)) {
const cloneArr = [];
for (let i = 0; i < obj.length; i++) {
cloneArr[i] = deepClone(obj[i]);
}
return cloneArr;
}
if (typeof obj === 'object') {
const cloneObj = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key]);
}
}
return cloneObj;
}
}
2、promiseAll异步实现
function promiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let completed = 0;
if (promises.length === 0) {
resolve(results);
} else {
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((result) => {
results[index] = result;
completed++;
if (completed === promises.length) {
resolve(results);
}
})
.catch(reject);
});
}
});
}
3、给你一个字符串s和一个字符串列表wordDict作为字典,请你判断是否可以利用字典中出现的单词拼接出s,不要求字典中出现的单词全部都使用,并且单词可以重复使用
例如: s="applepenapple" wordDict=["apple","pen"] 输出true
function wordBreak(s, wordDict) {
const n = s.length;
const dp = new Array(n + 1).fill(false);
dp[0] = true;
for (let i = 1; i <= n; i++) {
for (let j = 0; j < i; j++) {
if (dp[j] && wordDict.includes(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[n];
}
const s = "applepenapple";
const wordDict = ["apple", "pen"];
const result = wordBreak(s, wordDict);
console.log(result); // Output: true
//这段代码使用动态规划来检查字符串 `s` 是否可以通过字典 `wordDict` 中的单词拼接而成。
//在示例中,返回 `true`,因为 "applepenapple" 可以拆分为 "apple", "pen", "apple"。
4、给你一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c 使得a+b+c=0?请找出所有和为0且不重复的三元组,注意:答案中不包括重复的三元组
示例:输入:nums = [-1,0,1,2,-1,-4] 输出 [[-1,-1,2],[-1,0,2]]
function threeSum(nums) {
nums.sort((a, b) => a - b);
const result = [];
for (let i = 0; i < nums.length - 2; i++) {
if (i === 0 || (i > 0 && nums[i] !== nums[i - 1])) {
let lo = i + 1;
let hi = nums.length - 1;
const sum = 0 - nums[i];
while (lo < hi) {
if (nums[lo] + nums[hi] === sum) {
result.push([nums[i], nums[lo], nums[hi]);
while (lo < hi && nums[lo] === nums[lo + 1]) lo++;
while (lo < hi && nums[hi] === nums[hi - 1]) hi--;
lo++;
hi--;
} else if (nums[lo] + nums[hi] < sum) {
lo++;
} else {
hi--;
}
}
}
}
return result;
}
const nums = [-1, 0, 1, 2, -1, -4];
const result = threeSum(nums);
console.log(result); // Output: [[-1, -1, 2], [-1, 0, 1]]
//这段代码会找出数组 `nums` 中所有和为 0 的不重复三元组,并返回结果。
//在示例中,返回 `[[-1, -1, 2], [-1, 0, 1]]`。
5、实现一个stringfy,实现以后支持换行和缩进
function customStringify(obj, indent = 2) {
return JSON.stringify(obj, null, indent);
}
const obj = {
name: "John",
age: 30,
address: {
city: "New York",
zip: "10001",
},
};
const jsonString = customStringify(obj, 4);
console.log(jsonString);
//这个 `customStringify` 函数接受两个参数:要转换的对象和缩进级别(默认为2)。
//它使用 `JSON.stringify`,并通过传递缩进级别来支持换行和缩进。
6、求一个数所有质因子的最大和
function primeFactorsSum(n) {
let sum = 0;
for (let i = 2; i <= n; i++) {
while (n % i === 0) {
sum += i;
n /= i;
}
}
return sum;
}
const number = 30;
const result = primeFactorsSum(number);
console.log(result); // Output: 17 (2 + 3 + 5 + 7)
//这个函数遍历从2到给定数 `n` 的所有整数,找到所有质因子并求和。
7、实现一个带限制次数的请求方法 reuest(urls,limit);
function request(urls, limit) {
const results = [];
const inProgress = [];
let currentIndex = 0;
function fetchNext() {
if (currentIndex === urls.length) {
return Promise.resolve();
}
const url = urls[currentIndex];
const requestPromise = fetch(url)
.then((response) => response.json())
.then((data) => {
results[currentIndex] = data;
})
.finally(() => {
const index = inProgress.indexOf(requestPromise);
if (index !== -1) {
inProgress.splice(index, 1);
}
});
inProgress.push(requestPromise);
currentIndex++;
if (inProgress.length >= limit) {
return Promise.race(inProgress).then(fetchNext);
}
return fetchNext();
}
return fetchNext().then(() => results);
}
const urls = [...]; // Your array of URLs to request
const limit = 3; // Limit the number of concurrent requests
request(urls, limit).then((results) => {
console.log(results);
});
//这个函数使用 `fetch` 来并行请求一组 URL,但限制并发请求数量为 `limit`。
8、给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
function lowestCommonAncestor(root, p, q) {
if (root === null) return null;
if (root.val === p.val || root.val === q.val) return root;
const left = lowestCommonAncestor(root.left, p, q);
const right = lowestCommonAncestor(root.right, p, q);
if (left && right) return root;
return left || right;
}
// 示例用法
const root = new TreeNode(3);
root.left = new TreeNode(5);
root.right = new TreeNode(1);
root.left.left = new TreeNode(6);
root.left.right = new TreeNode(2);
root.right.left = new TreeNode(0);
root.right.right = new TreeNode(8);
root.left.right.left = new TreeNode(7);
root.left.right.right = new TreeNode(4);
const p = root.left;
const q = root.left.right.right;
const result = lowestCommonAncestor(root, p, q);
console.log(result.val); // Output: 5
//这段代码实现了一个二叉树,并查找了两个指定节点 `p` 和 `q` 的最近公共祖先。
9、promise.all的实现 及 promise.all串行执行的实现
function customPromiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let completedCount = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((result) => {
results[index] = result;
completedCount++;
if (completedCount === promises.length) {
resolve(results);
}
})
.catch(reject);
});
if (promises.length === 0) {
resolve(results);
}
});
}
const promises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3),
];
customPromiseAll(promises)
.then((results) => {
console.log(results); // Output: [1, 2, 3]
})
.catch((error) => {
console.error(error);
});
// 串行执行的 Promise.all
function customPromiseAllSerial(promises) {
return promises.reduce((prev, current) => prev.then(current), Promise.resolve([]));
}
const serialPromises = [
() => Promise.resolve(1),
() => Promise.resolve(2),
() => Promise.resolve(3),
];
customPromiseAllSerial(serialPromises)
.then((results) => {
console.log(results); // Output: [1, 2, 3]
})
.catch((error) => {
console.error(error);
});
10、输入一个n 返回一个1-n的全排列
function permute(n) {
const result = [];
const nums = Array.from({ length: n }, (_, index) => index + 1);
function backtrack(start) {
if (start === n) {
result.push([...nums]);
return;
}
for (let i = start; i < n; i++) {
[nums[start], nums[i]] = [nums[i], nums[start]];
backtrack(start + 1);
[nums[start], nums[i]] = [nums[i], nums[start]];
}
}
backtrack(0);
return result;
}
const n = 3;
const permutations = permute(n);
console.log(permutations);
//这个函数使用回溯算法生成了 1 到 `n` 的全排
11、loash.get()方法的实现 输入各种字符串 返回对应的结果
function customGet(obj, path, defaultValue) {
const keys = Array.isArray(path) ? path : path.split('.');
let result = obj;
for (const key of keys) {
if (result && typeof result === 'object' && key in result) {
result = result[key];
} else {
return defaultValue;
}
}
return result;
}
const data = {
user: {
name: 'John',
address: {
city: 'New York',
},
},
};
const userName = customGet(data, 'user.name', 'Unknown');
console.log(userName); // Output: 'John'
const country = customGet(data, 'user.address.country', 'Unknown');
console.log(country); // Output: 'Unknown'
//`customGet()` 函数接受一个对象 `obj`,一个路径字符串或路径数组 `path`,以及一个可选的默认值 `defaultValue`,并返回指定路径的值,如果路径无效,则返回默认值。
12、jsonp的实现
function jsonp(url, callbackName, callback) {
const script = document.createElement('script');
script.src = `${url}?callback=${callbackName}`;
document.body.appendChild(script);
window[callbackName] = (data) => {
callback(data);
document.body.removeChild(script);
};
}
// 使用示例
jsonp('https://example.com/api/data', 'myCallback', (data) => {
console.log(data);
});
13、给定一个字符串 判断其中的括号是不是都能匹配上
function isParenthesesMatch(str) {
const stack = [];
const openingBrackets = '([{';
const closingBrackets = ')]}';
for (let char of str) {
if (openingBrackets.includes(char)) {
stack.push(char);
} else if (closingBrackets.includes(char)) {
if (stack.length === 0) {
return false;
}
const lastOpenBracket = stack.pop();
if (
(char === ')' && lastOpenBracket !== '(') ||
(char === ']' && lastOpenBracket !== '[') ||
(char === '}' && lastOpenBracket !== '{')
) {
return false;
}
}
}
return stack.length === 0;
}
console.log(isParenthesesMatch('()[]{}')); // true
console.log(isParenthesesMatch('(]')); // false
//这个函数会遍历输入字符串,将遇到的开括号入栈,然后在遇到闭括号时检查是否与栈顶的开括号匹配。如果括号都匹配,最终栈应为空。
14、sum(a,b,c,d) 用 sum(a)(b)(c,d).counter()实现
function removeAdjacentDuplicates(str) {
return str.replace(/(.)\1+/g, '$1');
}
const input = 'aabbccd';
const result = removeAdjacentDuplicates(input);
console.log(result); // Output: 'abcd'
15、两个大数相加的实现
function addLargeNumbers(num1, num2) {
const maxLen = Math.max(num1.length, num2.length);
const result = [];
let carry = 0;
for (let i = 0; i < maxLen; i++) {
const digit1 = num1[num1.length - 1 - i] || 0;
const digit2 = num2[num2.length - 1 - i] || 0;
const sum = digit1 + digit2 + carry;
if (sum > 9) {
carry = 1;
result.unshift(sum - 10);
} else {
carry = 0;
result.unshift(sum);
}
}
if (carry > 0) {
result.unshift(carry);
}
return result.join('');
}
const num1 = '123456789012345678901234567890';
const num2 = '987654321098765432109876543210';
const sum = addLargeNumbers(num1, num2);
console.log(sum);
//这个函数用于将两个大数相加,它将大数转化为数组并模拟手工相加的方式。
16、call apply bind的实现及原理
// 实现 call
Function.prototype.customCall = function (context, ...args) {
context = context || window;
const fnKey = Symbol();
context[fnKey] = this;
const result = context[fnKey](...args);
delete context[fnKey];
return result;
};
// 实现 apply
Function.prototype.customApply = function (context, args) {
context = context || window;
const fnKey = Symbol();
context[fnKey] = this;
const result = context[fnKey](...args);
delete context[fnKey];
return result;
};
// 实现 bind
Function.prototype.customBind = function (context, ...args) {
context = context || window;
const fnKey = Symbol();
context[fnKey] = this;
return function (...innerArgs) {
const result = context[fnKey](...args, ...innerArgs);
delete context[fnKey];
return result;
};
};
// 示例用法
const person = {
name: 'John',
};
function greet(greeting) {
console.log(`${greeting}, ${this.name}`);
}
greet.customCall(person, 'Hello'); // Output: 'Hello, John'
greet.customApply(person, ['Hi']); // Output: 'Hi, John'
const greetHi = greet.customBind(person, 'Hi');
greetHi(); // Output: 'Hi, John'
17、二叉树的之子形遍历
function zigzagLevelOrder(root) {
if (!root) return [];
const result = [];
let isReverse = false;
const queue = [root];
while (queue.length) {
const level = [];
const levelSize = queue.length;
for (let i = 0; i < levelSize; i++) {
const node = queue.shift();
if (isReverse) {
level.unshift(node.val);
} else {
level.push(node.val);
}
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
result.push(level);
isReverse = !isReverse;
}
return result;
}
// 示例用法
const tree = {
val: 3,
left: {
val: 9,
left: null,
right: null,
},
right: {
val: 20,
left: {
val: 15,
left: null,
right: null,
},
right: {
val: 7,
left: null,
right: null,
},
},
};
const result = zigzagLevelOrder(tree);
console.log(result); // Output: [[3], [20, 9], [15, 7]]
//这个函数实现了二叉树的之字形层序遍历,并返回一个数组,其中包含每层的节点值。
18、给定一个数组找出所有三个数之和为0的所有组合
function threeSum(nums) {
const result = [];
nums.sort((a, b) => a - b); // 先对数组排序
for (let i = 0; i < nums.length - 2; i++) {
if (i === 0 || (i > 0 && nums[i] !== nums[i - 1])) {
let lo = i + 1;
let hi = nums.length - 1;
const sum = 0 - nums[i];
while (lo < hi) {
if (nums[lo] + nums[hi] === sum) {
result.push([nums[i], nums[lo], nums[hi]]);
while (lo < hi && nums[lo] === nums[lo + 1]) lo++;
while (lo < hi && nums[hi] === nums[hi - 1]) hi--;
lo++;
hi--;
} else if (nums[lo] + nums[hi] < sum) {
lo++;
} else {
hi--;
}
}
}
}
return result;
}
const nums = [-1, 0, 1, 2, -1, -4];
const result = threeSum(nums);
console.log(result); // Output: [[-1, -1, 2], [-1, 0, 1]]
19、二分查找
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
const sortedArray = [1, 3, 5, 7, 9, 11, 13, 15];
const target = 7;
const index = binarySearch(sortedArray, target);
console.log(index); // Output: 3
20、两个矩形相交处 输入 2个矩形的4个坐标
function isRectangleOverlap(rect1, rect2) {
return (
rect1[2] > rect2[0] && // rect1 right > rect2 left
rect1[0] < rect2[2] && // rect1 left < rect2 right
rect1[3] > rect2[1] && // rect1 bottom > rect2 top
rect1[1] < rect2[3] // rect1 top < rect2 bottom
);
}
const rect1 = [0, 0, 2, 2];
const rect2 = [1, 1, 3, 3];
const overlap = isRectangleOverlap(rect1, rect2);
console.log(overlap); // Output: true
21、两个有序链表的合并
class ListNode {
constructor(val) {
this.val = val;
this.next = null;
}
}
function mergeTwoLists(l1, l2) {
const dummyHead = new ListNode(0);
let current = dummyHead;
while (l1 !== null && l2 !== null) {
if (l1.val < l2.val) {
current.next = l1;
l1 = l1.next;
} else {
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
if (l1 !== null) {
current.next = l1;
} else {
current.next = l2;
}
return dummyHead.next;
}
// 示例用法
const l1 = new ListNode(1);
l1.next = new ListNode(2);
l1.next.next = new ListNode(4);
const l2 = new ListNode(1);
l2.next = new ListNode(3);
l2.next.next = new ListNode(4);
const mergedList = mergeTwoLists(l1, l2);
console.log(mergedList);
22、let arr = [{ id: '1', name: "河北省", children: [{ id: '1-1', name: "石家庄市", children: [{ id: '1-1-1', name: "新华区", }, { id: '1-1-2', name: "裕华区", }] }, { id: '1-2', name: "唐山市", children: [{ id: '1-2-1', name: "路北区", }, { id: '1-2-2', name: "路南区", }] }] // 实现函数 findAdrress(arr, id) 返回地址的拼接 比如 findAdrress(arr, '1-2-1') 返回河北省唐山市路北区
function findAddress(arr, id) {
for (const item of arr) {
if (item.id === id) {
return item.name;
}
if (item.children) {
const result = findAddress(item.children, id);
if (result) {
return item.name + result;
}
}
}
return null;
}
const addressData = [
{
id: '1',
name: '河北省',
children: [
{
id: '1-1',
name: '石家庄市',
children: [
{ id: '1-1-1', name: '新华区' },
{ id: '1-1-2', name: '裕华区' },
],
},
{
id: '1-2',
name: '唐山市',
children: [
{ id: '1-2-1', name: '路北区' },
{ id: '1-2-2', name: '路南区' },
],
},
],
},
];
const result = findAddress(addressData, '1-2-1');
console.log(result); // Output: '河北省唐山市路北区'
//这个函数用于查找嵌套对象数组 `arr` 中的地址,根据给定的 `id`,返回地址的拼接字符串。
24、输入一个字符串返回最长回文
function longestPalindrome(s) {
if (s.length < 2) return s;
let start = 0;
let maxLength = 1;
function expandAroundCenter(left, right) {
while (left >= 0 && right < s.length && s[left] === s[right]) {
const currentLength = right - left + 1;
if (currentLength > maxLength) {
maxLength = currentLength;
start = left;
}
left--;
right++;
}
}
for (let i = 0; i < s.length - 1; i++) {
expandAroundCenter(i, i); // odd length
expandAroundCenter(i, i + 1); // even length
}
return s.slice(start, start + maxLength);
}
const input = 'babad';
const result = longestPalindrome(input);
console.log(result); // Output: 'bab' or 'aba'
//这个函数使用中心扩展法来查找输入字符串 `s` 中的最长回文子串。
25、输入一个字符串返回最长无重复子串
function lengthOfLongestSubstring(s) {
const n = s.length;
let maxLength = 0;
const charMap = new Map();
let left = 0;
for (let right = 0; right < n; right++) {
if (charMap.has(s[right]) && charMap.get(s[right]) >= left) {
left = charMap.get(s[right]) + 1;
}
charMap.set(s[right], right);
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
const input = 'abcabcbb';
const result = lengthOfLongestSubstring(input);
console.log(result); // Output: 3 (for 'abc')
26、翻转链表
class ListNode {
constructor(val) {
this.val = val;
this.next = null;
}
}
function reverseList(head) {
let prev = null;
let current = head;
while (current !== null) {
const next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
// 示例用法
const head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
const reversedHead = reverseList(head);
console.log(reversedHead);
//这个函数用于翻转链表,返回一个新的链表头。
27、判断链接是否有环及环的入口
class ListNode {
constructor(val) {
this.val = val;
this.next = null;
}
}
function detectCycle(head) {
let slow = head;
let fast = head;
while (fast !== null && fast.next !== null) {
slow = slow.next;
fast = fast.next.next;
if (slow === fast) {
let entry = head;
while (entry !== slow) {
entry = entry.next;
slow = slow.next;
}
return entry;
}
}
return null;
}
// 示例用法
const head = new ListNode(3);
const node1 = new ListNode(2);
const node2 = new ListNode(0);
const node3 = new ListNode(-4);
head.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node1; // 创建循环
const entry = detectCycle(head);
console.log(entry); // Output: node1
//这个函数用于判断链表是否有环,如果有环则返回环的入口节点。
28、多维数组展示为一维
function flattenArray(arr) {
return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenArray(val)) : acc.concat(val), []);
}
const multiDimensionalArray = [1, [2, [3, 4], 5], 6];
const flattenedArray = flattenArray(multiDimensionalArray);
console.log(flattenedArray); // Output: [1, 2, 3, 4, 5, 6]
这个函数会将多维数组 `arr` 展平为一维数组
29、单个字符组成的数组统计每一个字符出现的次数
function countCharacters(arr) {
const charCount = {};
for (const char of arr) {
if (charCount[char]) {
charCount[char]++;
} else {
charCount[char] = 1;
}
}
return charCount;
}
const charArray = ['a', 'b', 'a', 'c', 'b', 'a'];
const characterCount = countCharacters(charArray);
console.log(characterCount); // Output: { 'a': 3, 'b': 2, 'c': 1 }
//这个函数会统计数组 `arr` 中每个字符出现的次数并返回一个对象。
30、自己实现promise
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.callbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.callbacks.forEach((callback) => callback.onFulfilled(value));
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = reason;
this.callbacks.forEach((callback) => callback.onRejected(reason));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value);
} else if (this.state === 'rejected') {
onRejected(this.value);
} else {
this.callbacks.push({
onFulfilled,
onRejected,
});
}
}
}
// 示例用法
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Hello, world!');
}, 1000);
});
promise.then(
(value) => {
console.log(value); // Output: 'Hello, world!'
},
(reason) => {
console.error(reason);
}
);
//这个示例只是 Promise 的一个极简化版本,用于演示 Promise 的核心概念。实际的 Promise 实现更加复杂,包括处理异步操作、链式调用等功能。
31、开方的实现
const number = 16;
const squareRoot = Math.sqrt(number);
console.log(squareRoot); // Output: 4
//这个方法会返回输入数字的平方根
32、斐波那契数列的实现
递归实现:
function fibonacciRecursive(n) {
if (n <= 1) {
return n;
}
return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
}
const n = 10;
console.log(fibonacciRecursive(n)); // Output: 55
迭代实现:
function fibonacciIterative(n) {
let a = 0;
let b = 1;
for (let i = 2; i <= n; i++) {
const temp = a + b;
a = b;
b = temp;
}
return b;
}
const n = 10;
console.log(fibonacciIterative(n)); // Output: 55
33、防抖和节流的实现
function debounce(func, delay) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
// 示例用法
function handleInput() {
console.log('Debounced input event');
}
const debouncedInput = debounce(handleInput, 300);
// 在输入框中触发事件,但处理程序会在 300 毫秒后执行
function throttle(func, delay) {
let lastExecTime = 0;
return function (...args) {
const currentTime = Date.now();
if (currentTime - lastExecTime >= delay) {
func.apply(this, args);
lastExecTime = currentTime;
}
};
}
// 示例用法
function handleScroll() {
console.log('Throttled scroll event');
}
const throttledScroll = throttle(handleScroll, 300);
// 当滚动事件触发时,处理程序每 300 毫秒执行一次
35、实现数组的map方法
function customMap(arr, callback) {
const result = [];
for (let i = 0; i < arr.length; i++) {
result.push(callback(arr[i], i, arr));
}
return result;
}
const numbers = [1, 2, 3, 4, 5];
const doubled = customMap(numbers, (num) => num * 2);
console.log(doubled); // Output: [2, 4, 6, 8, 10]
//这个 `customMap` 函数接受一个数组和一个回调函数,将回调函数应用于数组的每个元素,并返回一个新的数组。在示例中,`doubled` 数组包含了 `numbers` 数组中每个元素的两倍值