Javascript 降低嵌套for循环的时间复杂性
基本上,我试图降低我拥有的一系列函数的时间复杂度Javascript 降低嵌套for循环的时间复杂性,javascript,Javascript,基本上,我试图降低我拥有的一系列函数的时间复杂度 const companies = [ { staff: [ { id: 1, qualities: [ { id: 2, tags: [ 'efficient', 'hard-working' ] }
const companies = [
{
staff: [
{
id: 1,
qualities: [
{
id: 2,
tags: [
'efficient',
'hard-working'
]
}
]
}
]
}
]
因此,我有一个数组
的公司
,其中有另一个数组
的员工
,然后又有一个数组
的质量
,最后还有一个数组
的标签
现在我有了一个预先确定的标签列表,我需要为每个公司匹配用户
companies: [
xyz: [
{
tag: 'smart',
users: []
}
],
// ...
];
所以基本上我需要遍历每个预先确定的标签,然后遍历每个公司,然后遍历每个用户,遍历每个标签来创建这个视图
基本上是这样的
const tags = [
'smart',
'hard-working',
'efficient'
];
getUserTags(tagName) {
const users = [];
companies.forEach(company => {
company.users.forEach(user => {
user.tags.forEach(tag => {
if (tag === tagName) {
users.push(user);
}
});
});
});
return users;
}
正如你所看到的,这是超低效的,大O的结果是O(n^4),这很可怕
我怎样才能解决这个问题
可能有50个标记[…],因此对于每个标记,它必须[调用getUserTags
函数]循环遍历每个用户,然后循环遍历每个用户标记,以查看是否匹配以获得总计数
不,你不应该这样做。相反,只循环一次用户和每个用户的标记,并按标记名映射数据结构在数组中收集它们。使用类似
getUsersByTags(companies, tags) {
let map = new Map();
for (const tag of tags) {
map.set(tag, []);
}
for (const company of companies) {
for (const user of company.staff) {
for (const quality of user.qualities) {
for (const tag of quality.tags) {
const n = tag.name;
if (map.has(n))
map.get(n).push(user);
}
}
}
}
return map;
}
您无法避免遍历整个公司员工质量标签结构来访问所有标签数据。就时间复杂性而言,你说你需要4层抽象。(在对你的问题进行编辑之前,是3个问题:用户、质量、标签)。现在我们有了公司、员工、品质和标签。使用此结构,您应该期望O(n^4)。下面的代码不尝试更改复杂性级别,但可能会更快,因为它只保留计数而不是项目,并使用include来缩短循环的出口 这可以使用和来完成
我们使用
reduce
通过将标识为包含在每个质量项目中的标记值相加,从数组的累加中获取单个值。如果您只想对它们进行计数,不要将它们放入数组中,而只是增加一个整数。您是真的想让代码更快,还是更易于读取/维护?它们往往不是一回事。如果是前者,那么在最坏的情况下它现在有多慢?不,如果你的数据就是这样的结构,那么就无法避免完全遍历它。除了选择一个更合适的数据结构作为输入,你无法降低时间复杂度。@Bergi不幸的是,我确实需要将它们存储在数组中-因为我做了进一步的修改Minor:原始的公司
对象似乎有不正确的结构。哇,发布后几秒钟立即进行向下投票。甚至没有足够的时间阅读我的答案。下层选民愿意给出一个原因吗?谢谢,是的,实际上地图是不需要的。我们也可以使用includes
,因为一个标签在质量标签列表中出现多次是没有意义的。不清楚为什么这个解决方案会降低时间复杂度?@SmokeyDawson谢谢,将用户
重命名为公司
并不会真正改变我的答案。第二个代码段中的结构(公司:[…
)语法无效,我不知道该怎么办?同样在编辑中,您删除了正在计算标记的事实,并将其替换为仅通用的//do stuff
。在不知道结果是什么的情况下,我们无法建议任何更好的算法。好的,已更新,但答案的要点不变。无返回值。
let getCountOfTags = (users, tagName) => users.reduce(
(acc, item) => acc + item.qualities.reduce(
(qAcc, q) => qAcc + (q.tags.includes(tagName) ? 1 : 0),
0
),
0
);