给定正整数N ,任务是对从1到N的所有数字的二进制表示形式中的设置位数的总和进行计数。
例子:
Input: N = 3
Output: 4
1 + 1 + 2 = 4
Input: N = 16
Output: 33
方法:这里讨论了解决此问题的其他方法。在本文中,讨论了另一种具有时间复杂度O(logN)的方法。
检查下表中从1到N的数字的二进制表示形式:
Decimal | Binary | Set Bit Count |
---|---|---|
1 | 01 | 1 |
2 | 10 | 1 |
3 | 11 | 2 |
请注意,
- A中的每个备用位都被置位。
- B中的每2个备用位被置1。
- C中的每4个备用位被置1。
- D中的每8个备用位被置1。
- …..
- 这将继续以每2的幂次重复。
因此,我们将迭代直到数字中的位数。而且,我们不必迭代从1到n范围内的每个数字。
我们将执行以下操作以获得所需的结果。
- ,首先,我们将数字加1以补偿0。由于二进制数系统从0开始。所以现在n = n + 1。
- 到目前为止,我们将跟踪遇到的设置位的数量。我们将用n / 2对其进行初始化。
- 我们将保留一个2的幂的变量,以便跟踪我们正在计算的位。
- 我们将迭代直到2的乘方大于n。
- 我们可以通过将n除以当前2的幂来获得所有数字的当前位中0和1s的对数。
- 现在我们必须在设置的位数中添加位数。我们可以通过将0和1s的对数除以2来做到这一点,这将仅给我们1s的对数,然后,我们将其乘以2的当前幂以得到组中1的个数。
- 现在可能有机会获得成对的数字,该数字在组的中间位置,即1的数量小于该特定组中2的当前乘方。因此,我们将找到模数并将其添加到设置位的计数中,借助示例可以清楚地看出这一点。
示例:考虑N = 14
在上表中,共有28个设置位,从1到14。
我们将2 0视为A,将2 1视为B,将2 2视为C,将2 3视为D
首先我们将数字N加1,所以现在我们的N = 14 +1 = 15。
- A的计算(2 0 = 1)
15/2 = 7
A = 7的置位位数————>(i) - B的计算(2 ^ 1 = 2)
15/2 = 7 =>有7组0和1
现在,仅计算设置位的组数,我们必须将其除以2。
因此,7/2 =3。有3个设置位组。
并且这些组这次将包含等于2的幂的设置位,即2。因此,我们将设置位组的数量乘以2的幂
=> 3 * 2 = 6->(2i)
加
可能会有一些额外的1,因为未考虑第4组,因为该除法将只给我们整数值。因此,我们也必须添加它。注意:–仅当0和1的组数为奇数时,才会发生这种情况。
15%2 = 1->(2ii)
2i + 2ii => 6 +1 = 7 ————>(ii) - C的计算(2 ^ 2 = 4)
15/4 = 3 =>有3组0和1
设置位组的数量= 3/2 = 1
这些组中的置位位数= 1 * 4 = 4 —>(3i)
由于3为奇数,因此我们必须在未考虑的组中添加位
因此,15%4 = 3->(3ii)
3i + 3ii = 4 + 3 = 7 ————>(iii) - D的计算(2 ^ 3 = 8)
15/8 = 1 =>有1组0和1。现在,在这种情况下,只有一个组,也只有0个组。
设置的位组数= 1/2 = 0
这些组中的置位位数= 0 * 8 = 0 —>(4i)
由于组数是奇数,
因此,15%8 = 7->(4ii)
4i + 4ii = 0 + 7 = 7 ————>(iv)
此时,我们2的幂次幂变得大于数字,在本例中为15。 (2的幂= 16且16> 15)。因此,循环在此处终止。
最终输出= i + ii + iii + iv = 7 + 7 + 7 + 7 = 28
从1到14的设置位数为28。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to return the sum of the count
// of set bits in the integers from 1 to n
int countSetBits(int n)
{
// Ignore 0 as all the bits are unset
n++;
// To store the powers of 2
int powerOf2 = 2;
// To store the result, it is initialized
// with n/2 because the count of set
// least significant bits in the integers
// from 1 to n is n/2
int cnt = n / 2;
// Loop for every bit required to represent n
while (powerOf2 <= n) {
// Total count of pairs of 0s and 1s
int totalPairs = n / powerOf2;
// totalPairs/2 gives the complete
// count of the pairs of 1s
// Multiplying it with the current power
// of 2 will give the count of
// 1s in the current bit
cnt += (totalPairs / 2) * powerOf2;
// If the count of pairs was odd then
// add the remaining 1s which could
// not be groupped together
cnt += (totalPairs & 1) ? (n % powerOf2) : 0;
// Next power of 2
powerOf2 <<= 1;
}
// Return the result
return cnt;
}
// Driver code
int main()
{
int n = 14;
cout << countSetBits(n);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
// Function to return the sum of the count
// of set bits in the integers from 1 to n
static int countSetBits(int n)
{
// Ignore 0 as all the bits are unset
n++;
// To store the powers of 2
int powerOf2 = 2;
// To store the result, it is initialized
// with n/2 because the count of set
// least significant bits in the integers
// from 1 to n is n/2
int cnt = n / 2;
// Loop for every bit required to represent n
while (powerOf2 <= n)
{
// Total count of pairs of 0s and 1s
int totalPairs = n / powerOf2;
// totalPairs/2 gives the complete
// count of the pairs of 1s
// Multiplying it with the current power
// of 2 will give the count of
// 1s in the current bit
cnt += (totalPairs / 2) * powerOf2;
// If the count of pairs was odd then
// add the remaining 1s which could
// not be groupped together
cnt += (totalPairs % 2 == 1) ?
(n % powerOf2) : 0;
// Next power of 2
powerOf2 <<= 1;
}
// Return the result
return cnt;
}
// Driver code
public static void main(String[] args)
{
int n = 14;
System.out.println(countSetBits(n));
}
}
// This code is contributed by Princi Singh
Python3
# Python3 implementation of the approach
# Function to return the sum of the count
# of set bits in the integers from 1 to n
def countSetBits(n) :
# Ignore 0 as all the bits are unset
n += 1;
# To store the powers of 2
powerOf2 = 2;
# To store the result, it is initialized
# with n/2 because the count of set
# least significant bits in the integers
# from 1 to n is n/2
cnt = n // 2;
# Loop for every bit required to represent n
while (powerOf2 <= n) :
# Total count of pairs of 0s and 1s
totalPairs = n // powerOf2;
# totalPairs/2 gives the complete
# count of the pairs of 1s
# Multiplying it with the current power
# of 2 will give the count of
# 1s in the current bit
cnt += (totalPairs // 2) * powerOf2;
# If the count of pairs was odd then
# add the remaining 1s which could
# not be groupped together
if (totalPairs & 1) :
cnt += (n % powerOf2)
else :
cnt += 0
# Next power of 2
powerOf2 <<= 1;
# Return the result
return cnt;
# Driver code
if __name__ == "__main__" :
n = 14;
print(countSetBits(n));
# This code is contributed by AnkitRai01
C#
// C# implementation of the approach
using System;
class GFG
{
// Function to return the sum of the count
// of set bits in the integers from 1 to n
static int countSetBits(int n)
{
// Ignore 0 as all the bits are unset
n++;
// To store the powers of 2
int powerOf2 = 2;
// To store the result, it is initialized
// with n/2 because the count of set
// least significant bits in the integers
// from 1 to n is n/2
int cnt = n / 2;
// Loop for every bit required to represent n
while (powerOf2 <= n)
{
// Total count of pairs of 0s and 1s
int totalPairs = n / powerOf2;
// totalPairs/2 gives the complete
// count of the pairs of 1s
// Multiplying it with the current power
// of 2 will give the count of
// 1s in the current bit
cnt += (totalPairs / 2) * powerOf2;
// If the count of pairs was odd then
// add the remaining 1s which could
// not be groupped together
cnt += (totalPairs % 2 == 1) ?
(n % powerOf2) : 0;
// Next power of 2
powerOf2 <<= 1;
}
// Return the result
return cnt;
}
// Driver code
public static void Main(String[] args)
{
int n = 14;
Console.WriteLine(countSetBits(n));
}
}
// This code is contributed by 29AjayKumar
Javascript
输出:
28