数组转树
题目:
const input = [
{id: 1, parentId: null},
{id: 2, parentId: 1},
{id: 3, parentId: 2},
];
转换成:
const output = {
id: 1,
children: [
{
id: 2,
children: [
{
id: 3,
},
],
},
],
};
解题:首先用一个map将数组所有项保存下来,key是每一项的id,value是每一项本身。再循环这个map,查找每一项的parentId,如果不存在则这一项是根,存在就把这一项push到parentId对像的children中。
function arrToTree(arr) {
const result = [];
// 先将数组每一项保存到map中
const map = arr.reduce((acc, cur) => {
acc[cur.id] = cur;
return acc;
}, {});
// 循环每一项,放到父元素的children中
for (const key in map) {
const item = map[key];
if (item.parentId === null) { // 根直接push到result
result.push(item);
} else {
const parent = map[item.parentId]; // 获取这一项的父对象
if (parent) {
parent.children = parent.children || [];
parent.children.push(item); // 把这一项push到父对象的children中
}
}
}
return result;
}
控制请求最大并发数
function control(list, num) {
let activeCount = 0; // 当前并发数
const fn = () => {
// 当前并发数大于给定的并发数 或 请求列表为空时,直接返回
if (activeCount > num || !list.length) return;
const f = list.shift();
activeCount++; // 并发数+1
f().finally(() => {
activeCount--; // 执行完一个后,并发数-1,执行下一个
fn();
});
};
const max = Math.min(list.length, num); // 兼容num > list.length,这种情况下,最大并发数为list.length
for (let i = 0; i < max; i++) {
fn();
}
}
给定一个数组 nums 和一个目标值 target,在该数组中找出和为目标值的两个数d
例如 nums: [8, 2, 6, 5, 4, 1, 3] ; target:7;return [2,5]
function twoNumber(nums, target) {
const map = new Map(); // 使用map保存已经遍历过的元素
for (let i = 0; i < nums.length; i++) {
const el = nums[i];
if (map.has(target - el)) { // 如果map中存在目标值,说明找到了
return [target - el, el];
} else {
map.set(el, el); // 保存遍历过的元素
}
}
return [];
}
输入一个字符串,找到第一个不重复字符的下标。例如:'abcabcde' => 6
题解:先遍历整个字符串将出现的个数用map保存下来,再遍历这个map找到第一个不重复的字符即可。
function findOneStr(str) {
const map = new Map(); // map的key是字符本身,value是重复的次数
for (const v of str) {
const count = map.get(v);
map.set(v, count ? count + 1 : 1); // 如果已存在则加1,不存在设为1
}
for (const [k, v] of map) {
if (v === 1) { // 找到第一个不重复的字符
return str.indexOf(k);
}
}
return -1;
}
斐波那契数列: 一个人正在爬楼梯,楼梯有 n 级台阶。每次这个人可以爬1级或2级台阶。请问这个人有多少种不同的方法爬到楼梯的顶部?
题解:爬到第 n 级台阶的方法数等于爬到第 n−1 级台阶的方法数与爬到第 n−2 级台阶的方法数之和。用公式表示就是:f(n)=f(n−1)+f(n−2)
function climbStairs(n) {
if (n <= 2) { return n; } //边界条件,当只有一层或两层时,对应只有一种和两种方法
let prev1 = 1, prev2 = 2; // 记录前两次的数据
for (let i = 3; i <= n; i++) {
const curr = prev1 + prev2;
prev1 = prev2; //更新前两次数据
prev2 = curr;
}
return prev2;
}
翻转链表
题解:通过迭代的方法,逐个翻转链表的节点。使用三个指针:prev、curr 和 next,prev 指向已经翻转的部分,curr 指向当前正在处理的节点,next 用于临时保存下一个节点。
function reverseList(head) {
let prev = null;
let curr = head;
while (curr !== null) {
let next = curr.next; // 临时保存下一个节点
curr.next = prev; // 翻转当前节点的指针
prev = curr; // 将prev指针移动到当前节点
curr = next; // 将curr指针移动到下一个节点
}
return prev; // prev最终会指向新链表的头节点
}