【问题标题】:All combinations without repetitions with specific cardinality所有没有重复且具有特定基数的组合
【发布时间】:2014-09-01 17:56:43
【问题描述】:

我有一个数组:

[a, b, c, d, e, f, ... , z]

我会生成所有可能的子数组的集合,没有重复,其基数在 X 和 Y 之间。

假设 php:

$array = array(1, 2, 3, 4, 5, 6, 7, 8);

$results = myFunction($array, 3, 5);

我的函数应该返回如下内容:

array( 
    array(1, 2, 3),
    array(1, 2, 4),
    ...
    array(4, 5, 6, 7, 8),
);

我的尝试是以二进制计数,从 0 到 2^n(其中 n 是集合的基数),如果 1s 的数量在 X 和 Y 之间,则添加由 1s 元素组成的数组到结果集。

例如。

8  = 0000 0111 => add (6,7,8) to result
9  = 0000 1000 => no 
10 = 0000 1001 => no
...

但它非常丑陋! 有更好的算法吗?

我正在使用 php,但请随意使用您喜欢的任何语言。

【问题讨论】:

  • 你应该使用递归。另请注意,结果集可能非常大——这可能是了解迭代器的好机会。 (是的,PHP 支持。)
  • PHP array combinations的可能重复
  • (使用从 X 到 Y 的外循环,或者更巧妙一点,调整递归以产生只要 X 的部分结果)

标签: php algorithm combinations


【解决方案1】:

一个非常简单的解决方案(我认为需要生成器,它是 php 5.5+)

// generate combinations of size $m
function comb($m, $a) {
    if (!$m) {
        yield [];
        return;
    }
    if (!$a) {
        return;
    }
    $h = $a[0];
    $t = array_slice($a, 1);
    foreach(comb($m - 1, $t) as $c)
        yield array_merge([$h], $c);
    foreach(comb($m, $t) as $c)
        yield $c;
}

然后

$a = ['a','b','c','d','e','f', 'g'];

foreach(range(3, 5) as $n)
    foreach(comb($n, $a) as $c)
        echo join(' ', $c), "\n";

【讨论】:

  • 这是我第一次在 php.ini 中看到生成器。很高兴知道!谢谢
  • @marka.thore:不客气。但请记住,这段代码并不是特别有效。
  • 你的意思是发电机效率不高?怎样才能更有效地做到这一点(不是代码,只是想法)?
  • @marka.thore:不知道生成器...但是如果性能很重要,迭代算法将比递归算法更好。搜索“按字典顺序生成组合”。
猜你喜欢
  • 2018-09-03
  • 2015-05-19
  • 2022-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多