布尔数组的排列

Posted

技术标签:

【中文标题】布尔数组的排列【英文标题】:Permutations of a boolean array 【发布时间】:2017-02-13 07:26:17 【问题描述】:

如果我有一个 n 长度的布尔值数组,我如何遍历数组的所有可能排列?

例如,对于一个大小为 3 的数组,有八种可能的排列:

[0,0,0]
[0,0,1]
[0,1,0]
[0,1,1]
[1,0,0]
[1,0,1]
[1,1,0]
[1,1,1]

附:我在 C 中工作,尽管我不一定要寻找特定于语言的答案。只是试图找到一种有效的算法来处理大型数组和许多可能的排列。

【问题讨论】:

【参考方案1】:

要为长度为 n 的向量制作通用 C 语言解决方案(只要问题标签是 C),您可以使用整数变量 i 的二进制表示:[0,2^n) 其中 n 是数组的长度,并且在 单个循环使用位运算符迭代所有向量。

【讨论】:

使用位运算符来提高效率是有意义的。您将如何在单个循环中进行迭代? for (i = 0; i Gene 为你实现了这个算法。 @Kaponir ^ 是 C 中的 XOR 运算符 @M.M 从我还是数学系的学生开始,为了清晰起见,我更喜欢数学符号。也许是因为我是建筑师,也许是因为我和聪明人一起工作,而不是机器人。【参考方案2】:

在二进制中实现“加1”:

#include <stdio.h>

void add1(int *a, int len) 
  int carry = 1;
  for (int i = len - 1; carry > 0 && i >= 0; i--) 
    int result = a[i] + carry;
    carry = result >> 1;
    a[i] = result & 1;
  


void print(int *a, int len) 
  printf("[");
  for (int i = 0; i < len; i++) 
    if (i > 0) printf(",");
    printf("%d", a[i]);
  
  printf("]\n");


int main(void) 
  int a[3] =  0 ;
  int n = sizeof a / sizeof a[0];
  for (int i = 0; i < (1 << n); i++) 
    print(a, n);
    add1(a, n);
  

编译运行:

$ gcc foo.c -o foo
$ ./foo
[0,0,0]
[0,0,1]
[0,1,0]
[0,1,1]
[1,0,0]
[1,0,1]
[1,1,0]
[1,1,1]

【讨论】:

如果我这样做,我是否会限制我系统上 int 的位长度?比如我有 50 个项目,会不会超过 int[] a 中的位数? @piper1935 您认为这段代码的哪一部分受限于您系统上 int 的位长度? @piper1935 没有和没有。 是的,这仅限于 n &lt;= 30(如果您有 32 位整数),否则 1 &lt;&lt; n 会导致未定义的行为。通过一些代码修改,限制可以增加到n &lt;= 63 @M.M 确实,小测试主要限于打印 20 亿个数字。但是作为问题答案的 add1() 函数将适用于长度不超过 20 亿的数组。如果我仅通过检查数组是否返回全零来实现测试主程序,它将循环遍历所有 2^20 亿个数组值。我不想等待它。【参考方案3】:

如果你真的需要数组的每一个排列。更简洁的方法可以是 std::next_permutation()

do
    std::cout<<v[0]<<" "<<v[1]<<" "<<v[2]<<" "<<v[3]<<std::endl;


while(std::next_permutation(v.begin(),v.end()));

理论复杂度与“加1”或其他方法相同。另外,只有 STL 会为您完成这项工作。

【讨论】:

这是一道 C 题,不涉及 C++。 @Deduplicator,你知道,一点点 C++ 也无妨。【参考方案4】:

使用 GMP 可以使这更容易一些,特别是如果您真的不需要实际的数组,只需测试以下内容即可:

#include <gmp.h>

...
int numbits = 3;  // Insert whatever you want
mpz_t curperm;
mpz_init(curperm);

for (; mpz_sizeinbase(curperm, 2) <= numbits; mpz_add_ui(curperm, curperm, 1)) 
    ... test specific bits w/mpz_tstbit(curperm, #) instead of array check of curperm[#] ...


mpz_clear(curperm);

【讨论】:

以上是关于布尔数组的排列的主要内容,如果未能解决你的问题,请参考以下文章

首先按布尔列对数组进行排序,然后按字符串列排序

将布尔对象数组转换为布尔原始数组? [复制]

C#如何 将一个布尔型数组全部 填充为false

Numpy 布尔型数组

通过布尔掩码数组选择numpy数组的元素

Java 通过另一个大小为 n 的布尔数组过滤数组