给定一个长度为N的整数数组(任意大数字)。如何计算数组中设置的位数?
一种简单的方法是,创建一种有效的方法来对一个字中的设置位进行计数(最显着的大小,通常等于处理器的位长),然后从数组的各个元素中添加位。
存在多种计数整数的设置位的方法,例如,请参见此方法。这些方法最好运行O(logN),其中N是位数。注意,在处理器N上是固定的,可以在32位计算机上以O(1)时间完成计数,而与总置位位数无关。总的来说,数组中的位可以用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;
}