IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

JavaScript 快速组合算法

岁月如歌 2009-10-13 22:52:51 累计浏览 2,356 次
本机暂存
/**
 * 快速组合算法
 * 从 n 中任选 m(0 < m <= n) 个数的所有组合
 */
function quick_combine(n, m) {
    var t = ((1 << n) - (1 << n - m)).toString(2),
        r = [], s, p1, p2;
    while((r.push(t), p1 = t.indexOf("10")) >= 0) {
        s  = t.slice(0, p1);
        p2 = s.indexOf("1");
        t = (p2 > 0 ? ((1 << p1) - (1 << p2)).toString(2) : s)
             + "01" + t.slice(p1 + 2);
    }
    return r;
}

算法思路:

假设场景为从 [a, b, c, d, e] 里, 5 选 3.

先设定第一个和最后一个组合为:
s = 1 1 1 0 0 // a,b,c
e = 0 0 1 1 1 // c,d,e

Step1. 从左到右找出第 i 个组合中的 10, 转换为 01, 并将 01 左边的 1 全部移动到最左边,得到新组合 t
Step2. 如果 t 不为 e, 继续 Step1

按照以上思路,可以得到

1 1 1 0 0
1 1 0 1 0
1 0 1 1 0
0 1 1 1 0
1 1 0 0 1
1 0 1 0 1
0 1 1 0 1
1 0 0 1 1
0 1 0 1 1
0 0 1 1 1

共 10 种组合

网上流传的递归方案(好像是月影写的?没找到源头):

/**
 * 递归组合算法
 * 从 arr[1...n] 中任选 num(0 < num <= n) 个数的所有组合
 */
function combine(arr, num) {
    var r = [];
    (function f(t, a, n) {
        if (n == 0) return r.push(t);
        for (var i = 0, l = a.length; i <= l - n; i++) {
            f(t.concat(a[i]), a.slice(i + 1), n - 1);
        }
    })([], arr, num);
    return r;
}

两种方案的性能对比: combine-test.html

在 Firefox, Chrome, Safari 浏览器中,快速组合算法优势非常明显。
在 IE 浏览器中,计算量比较小时,快速组合算法依旧有优势;但计算量大时,无优势,甚至不如递归。

2009-09-27: 修改快速组合算法,用 Math 代替 regex replace, 性能立刻提升,在所有浏览器下保持优势。

51js 讨论贴:http://bbs.51js.com/viewthread.php?tid=85574

同分类推荐文章

  1. 对基本有序的序列排序算法 (2026-06-11 17:46:49)
  2. Four Levels Of Customer Understanding (2026-05-22 21:00:00)
  3. 除法的意义 (2026-04-12 20:52:17)

查看更多 算法 文章 →

建议继续学习

  1. 如何成为Python高手 (累计阅读 54,992)
  2. JQuery实现Excel表格呈现 (累计阅读 48,352)
  3. 深入理解Javascript之执行上下文(Execution Context) (累计阅读 18,411)
  4. 从输入 URL 到页面加载完成的过程中都发生了什么事情? (累计阅读 15,938)
  5. 图片动态局部毛玻璃模糊效果的实现 (累计阅读 14,849)
  6. 天朝第二代身份证号码的验证机制 (累计阅读 14,764)
  7. HTML 5 的data-* 自定义属性 (累计阅读 14,353)
  8. 分享一个JQUERY颜色选择插件 (累计阅读 14,225)
  9. 什么是全栈工程师? (累计阅读 14,041)
  10. Linux 性能监控、测试、优化工具 (累计阅读 13,013)