javascript - 计算处理组合javascript的时间
问题描述
我有这个功能:https ://rosettacode.org/wiki/Combinations#ES6
在我的环境console.log(show(comb(3,15)));
中(与下面的这个片段相同)采取 aprox。4秒处理
如果我尝试console.log(show(comb(3,16)));
采取aprox。16 秒
如果我尝试console.log(show(comb(3,17)));
采取aprox。90 秒
但是如果我尝试过:console.log(show(comb(3,20)));
经过一小时的过程还没有完成,我已经停止了它。
问题是:
如何预先计算处理时间comb(3,50)
或comb(3,80)
?
(() => {
'use strict';
// COMBINATIONS -----------------------------------------------------------
// comb :: Int -> Int -> [[Int]]
const comb = (m, n) => combinations(m, enumFromTo(0, n - 1));
// combinations :: Int -> [a] -> [[a]]
const combinations = (k, xs) =>
sort(filter(xs => k === xs.length, subsequences(xs)));
// GENERIC FUNCTIONS -----------------------------------------------------
// cons :: a -> [a] -> [a]
const cons = (x, xs) => [x].concat(xs);
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
// filter :: (a -> Bool) -> [a] -> [a]
const filter = (f, xs) => xs.filter(f);
// foldr (a -> b -> b) -> b -> [a] -> b
const foldr = (f, a, xs) => xs.reduceRight(f, a);
// isNull :: [a] -> Bool
const isNull = xs => (xs instanceof Array) ? xs.length < 1 : undefined;
// show :: a -> String
const show = x => JSON.stringify(x) //, null, 2);
// sort :: Ord a => [a] -> [a]
const sort = xs => xs.sort();
// stringChars :: String -> [Char]
const stringChars = s => s.split('');
// subsequences :: [a] -> [[a]]
const subsequences = xs => {
// nonEmptySubsequences :: [a] -> [[a]]
const nonEmptySubsequences = xxs => {
if (isNull(xxs)) return [];
const [x, xs] = uncons(xxs);
const f = (r, ys) => cons(ys, cons(cons(x, ys), r));
return cons([x], foldr(f, [], nonEmptySubsequences(xs)));
};
return nonEmptySubsequences(
(typeof xs === 'string' ? stringChars(xs) : xs)
);
};
// uncons :: [a] -> Maybe (a, [a])
const uncons = xs => xs.length ? [xs[0], xs.slice(1)] : undefined;
// TEST -------------------------------------------------------------------
// return show(
// comb(3, 5)
// );
console.log(show(comb(3,15)));
})();
解决方案
使用二项式系数。处理时间comb(3,n)
是n choose 3
,n*(n-1)*(n-2)/6
因此是O(n^3)
。例如,增加n
10 倍应该会使运行时间增加大约 1000 倍。
20 choose 3
只有 1140,所以如果生成它们需要一个多小时,那么所讨论的算法并不是特别好。此外,和之间的差距20 choose 3
并17 choose 3
没有太大,以至于它真正解释了时差。因此,渐近分析只是暗示正在发生的事情。实际的运行时间似乎更糟。
推荐阅读
- python - Youtube API - python 数据下载脚本错误
- autocomplete - 在实时模板中记录下一行/上一行代码 (JetBrains IDE)
- javascript - 当我执行查询 gV().ToList() 时,如何让 gremlin 返回顶点的属性?当前返回未定义
- php - assertDatabaseHas 失败说“表是空的”
- flutter - 使用 Intl 包 (DateFormat) 时项目无法编译
- java - 安卓 X 项目
- java - 使用 DBMS_CRYPTO 但使用 dbms_obfuscation_toolkit 时出错
- javascript - 当请求已经发布但响应尚未到来时,如何防止刷新浏览器窗口?
- grafana - Grafana 警报中的自定义 json 正文
- dialogflow-es - 警告,基于 GCLOUD_PROJECT 估计 Firebase 配置。初始化 firebase-admin 可能会失败