📜  计算(大)数组中设置位数的程序

📅  最后修改于: 2021-09-16 11:15:16             🧑  作者: Mango

给定一个长度为 N(任意大的数)的整数数组。如何计算数组中设置的位数?

简单的方法是,创建一种有效的方法来计算一个字中的设置位(最显着的大小,通常等于处理器的位长度),并从数组的各个元素中添加位。

存在多种计算整数集位的方法,例如参见this。这些方法最多运行 O(logN),其中 N 是位数。请注意,在处理器 N 是固定的,计数可以在 O(1) 时间内在 32 位机器上完成,而不管设置的总位数。总的来说,数组中的位可以在 O(n) 时间内计算,其中 ‘n’ 是数组大小。

但是,当数组很大时,查表将是更有效的方法。存储可以处理 2 32 个整数的表查找是不切实际的。

以下代码说明了对随机生成的 64 K 整数数组中的设置位进行计数的简单程序。这个想法是生成对前 256 个数字(一个字节)的查找,并在字节边界处打破数组的每个元素。使用 C/C++ 预处理器的元程序生成用于计算字节中设置位的查找表。

元程序背后的数学推导从下表中可以明显看出(添加列和行索引以获取数字,然后查看表格以获取该数字中的设置位。例如,要获取 10 中的设置位,它可以是从命名为 8 的行和命名为 2 的列中提取,

0, 1, 2, 3
 0 - 0, 1, 1, 2 -------- GROUP_A(0)
 4 - 1, 2, 2, 3 -------- GROUP_A(1)
 8 - 1, 2, 2, 3 -------- GROUP_A(1)
12 - 2, 3, 3, 4 -------- GROUP_A(2)
16 - 1, 2, 2, 3 -------- GROUP_A(1)
20 - 2, 3, 3, 4 -------- GROUP_A(2)
24 - 2, 3, 3, 4 -------- GROUP_A(2)
28 - 3, 4, 4, 5 -------- GROUP_A(3) ... so on

从表中可以看出,无论是在表中还是在组参数中,都有一个以 4 的倍数出现的模式。该序列可以概括为代码中所示。

复杂:

除了遍历数组之外,所有操作都需要 O(1)。时间复杂度为 O(n),其中 ‘n’ 是数组的大小。空间复杂度取决于生成查找的元程序。

代码:

C++
#include 
#include  
using namespace std; 
  
  
/* Size of array 64 K */
#define SIZE (1 << 16) 
  
/* Meta program that generates set bit count 
array of first 256 integers */
  
/* GROUP_A - When combined with META_LOOK_UP 
generates count for 4x4 elements */
  
#define GROUP_A(x) x, x + 1, x + 1, x + 2 
  
/* GROUP_B - When combined with META_LOOK_UP 
generates count for 4x4x4 elements */
  
#define GROUP_B(x) GROUP_A(x), GROUP_A(x+1), GROUP_A(x+1), GROUP_A(x+2) 
  
/* GROUP_C - When combined with META_LOOK_UP 
generates count for 4x4x4x4 elements */
  
#define GROUP_C(x) GROUP_B(x), GROUP_B(x+1), GROUP_B(x+1), GROUP_B(x+2) 
  
/* Provide appropriate letter to generate the table */
  
#define META_LOOK_UP(PARAMETER)\ 
GROUP_##PARAMETER(0),\ 
GROUP_##PARAMETER(1),\ 
GROUP_##PARAMETER(1),\ 
GROUP_##PARAMETER(2)\ 
  
int countSetBits(int array[], size_t array_size) 
{ 
int count = 0; 
  
/* META_LOOK_UP(C) - generates a table of 256 integers whose 
    sequence will be number of bits in i-th position 
    where 0 <= i < 256 
*/
  
    /* A static table will be much faster to access */
    static unsigned char const look_up[] = { META_LOOK_UP(C) }; 
  
    /* No shifting funda (for better readability) */
    unsigned char *pData = NULL; 
  
for(size_t index = 0; index < array_size; index++) 
{ 
    /* It is fine, bypass the type system */
    pData = (unsigned char *)&array[index]; 
  
    /* Count set bits in individual bytes */
    count += look_up[pData[0]]; 
    count += look_up[pData[1]]; 
    count += look_up[pData[2]]; 
    count += look_up[pData[3]]; 
} 
  
return count; 
} 
  
/* Driver program, generates table of random 64 K numbers */
int main() 
{ 
int index; 
int random[SIZE]; 
  
/* Seed to the random-number generator */
srand((unsigned)time(0)); 
  
/* Generate random numbers. */
for( index = 0; index < SIZE; index++ ) 
{ 
    random[index] = rand(); 
} 
  
cout << "Total number of bits = "<< countSetBits(random, SIZE); 
return 0; 
} 
  
// This is code is contributed by rathbhupendra


C
#include 
#include 
#include 
  
/* Size of array 64 K */
#define SIZE (1 << 16)
  
/* Meta program that generates set bit count
   array of first 256 integers */
  
/* GROUP_A - When combined with META_LOOK_UP
   generates count for 4x4 elements */
  
#define GROUP_A(x) x, x + 1, x + 1, x + 2
  
/* GROUP_B - When combined with META_LOOK_UP
   generates count for 4x4x4 elements */
  
#define GROUP_B(x) GROUP_A(x), GROUP_A(x+1), GROUP_A(x+1), GROUP_A(x+2)
  
/* GROUP_C - When combined with META_LOOK_UP
   generates count for 4x4x4x4 elements */
  
#define GROUP_C(x) GROUP_B(x), GROUP_B(x+1), GROUP_B(x+1), GROUP_B(x+2)
  
/* Provide appropriate letter to generate the table */
  
#define META_LOOK_UP(PARAMETER) \
   GROUP_##PARAMETER(0),  \
   GROUP_##PARAMETER(1),  \
   GROUP_##PARAMETER(1),  \
   GROUP_##PARAMETER(2)   \
  
int countSetBits(int array[], size_t array_size)
{
   int count = 0;
  
   /* META_LOOK_UP(C) - generates a table of 256 integers whose
      sequence will be number of bits in i-th position
      where 0 <= i < 256
   */
  
    /* A static table will be much faster to access */
       static unsigned char const look_up[] = { META_LOOK_UP(C) };
  
    /* No shifting funda (for better readability) */
    unsigned char *pData = NULL;
  
   for(size_t index = 0; index < array_size; index++)
   {
      /* It is fine, bypass the type system */
      pData = (unsigned char *)&array[index];
  
      /* Count set bits in individual bytes */
      count += look_up[pData[0]];
      count += look_up[pData[1]];
      count += look_up[pData[2]];
      count += look_up[pData[3]];
   }
  
   return count;
}
  
/* Driver program, generates table of random 64 K numbers */
int main()
{
   int index;
   int random[SIZE];
  
   /* Seed to the random-number generator */
   srand((unsigned)time(0));
  
   /* Generate random numbers. */
   for( index = 0; index < SIZE; index++ )
   {
      random[index] = rand();
   }
  
   printf("Total number of bits = %d\n", countSetBits(random, SIZE));
   return 0;
}


如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。