功率设定元素的长度

时间:2011-09-06 23:30:36

标签: php set powerset

给定PHP中的元素数组,我希望创建一个新的二维数组,其中只包含特定长度的幂集的元素。例如,对于以下数组:

array(4) {
    0 => 'A',
    1 => 'B',
    2 => 'C',
    3 => 'D'
}

如果我要运行函数fixed_length_power_set( $arr, 2 ),那么我希望它返回:

array(6) {
    0 => array(2) {
        0 => 'A',
        1 => 'B'
    }
    1 => array(2) {
        0 => 'A',
        1 => 'C'
    }

    2 => array(2) {
        0 => 'A',
        1 => 'D'
    }
    3 => array(2) {
        0 => 'B',
        1 => 'C'
    }
    4 => array(2) {
        0 => 'B',
        1 => 'D'
    }
    5 => array(2) {
        0 => 'C',
        1 => 'D'
    }
}

虽然我可以考虑一些规则来概括这个过程,但出于某些原因我似乎无法将其转化为代码。有没有人有建议?

2 个答案:

答案 0 :(得分:3)

使用简单的递归算法:对于大小为k的所有子集n的集合,

  • 如果n == k,则返回包含整个集合的集合;

  • 如果k == 1返回所有单身人士的集合;

  • 否则从集合中删除元素x:现在您需要剩余集合中所有大小为k-1的子集(即包含x的子集),如以及剩余集合中k的所有子集(不包括x的那些)。

在PHP伪代码中:

function subsets_n($arr, $k)
{
  if (count($arr) < $k) return array();
  if (count($arr) == $k) return array(0 => $arr);

  $x = array_pop($arr);
  if (is_null($x)) return array();

  return array_merge(subsets_n($arr, $k),
                     merge_into_each($x, subsets_n($arr, $k-1)) );
}

此处merge_into_each()x添加到集合中的每个数组:

function merge_into_each($x, $arr)
{
  foreach ($arr as &$a) array_push($a, $x);
  return $arr;
}

答案 1 :(得分:0)

我不是PHP专家,所以我会用伪代码回答。既然您似乎在询问数组和子序列(即使您使用英语单词“sets”和“subsets”),我也会这样做。我将使用符号arr[m:n]来表示构建一个长度为n - m + 1的全新数组,该数组会复制m, m+1, ..., n中的元素arr

fun subsequences(arr, len) {
    answer = new empty array

    // base case 1: we haven't got a enough members in the
    // array to make a subsequence that long, so there are
    // no subsequences of that length
    if(arr.length < len) return answer

    // base case 2: we're only looking for trivial subsequences
    if(len <= 0) {
        trivial = new empty array
        prepend trivial to answer
        return answer
    }

    // choose the first element in the subsequence nondeterministically
    for each i from 0 to arr.length - 1 {
        // since we know the sequence starts with arr[i], the
        // remainder of the sequence must come from the elements
        // after index i
        subanswer = subsequences(arr[i+1:arr.length], len-1)
        for each subsequence in subanswer, prepend arr[i] to subsequence
        answer = concat(subanswer, answer)
    }
}