给定一个长度为 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 现场工作专业课程和学生竞争性编程现场课程。