本文概述给定正整数n, 以二进制表示形式表示从1到n的所有数字的置位位数。
例子:
Input: n = 3
Output:4Input: n = 6
Output: 9Input: n = 7
Output: 12Input: n = 8
Output: 13
资料来源:亚马逊面试问题
方法1(简单)
一个简单的解决方案是运行一个从1到n的循环, 并对从1到n的所有数字中的设置位计数进行求和。
C ++
// A simple program to count set bits
// in all numbers from 1 to n.
#include <
stdio.h>
// A utility function to count set bits
// in a number x
unsigned int countSetBitsUtil(unsigned int x);
// Returns count of set bits present in all
// numbers from 1 to n
unsigned int countSetBits(unsigned int n)
{
int bitCount = 0;
// initialize the resultfor ( int i = 1;
i <
= n;
i++)
bitCount += countSetBitsUtil(i);
return bitCount;
}// A utility function to count set bits
// in a number x
unsigned int countSetBitsUtil(unsigned int x)
{
if (x <
= 0)
return 0;
return (x % 2 == 0 ? 0 : 1) + countSetBitsUtil(x / 2);
}// Driver program to test above functions
int main()
{
int n = 4;
printf ( "Total set bit count is %d" , countSetBits(n));
return 0;
}
Java
// A simple program to count set bits
// in all numbers from 1 to n.class GFG{// Returns count of set bits present
//in all numbers from 1 to n
static int countSetBits( int n)
{
// initialize the result
int bitCount = 0 ;
for ( int i = 1 ;
i <
= n;
i++)
bitCount += countSetBitsUtil(i);
return bitCount;
}// A utility function to count set bits
// in a number x
static int countSetBitsUtil( int x)
{
if (x <
= 0 )
return 0 ;
return (x % 2 == 0 ? 0 : 1 ) +
countSetBitsUtil(x / 2 );
}// Driver program
public static void main(String[] args)
{
int n = 4 ;
System.out.print( "Total set bit count is " );
System.out.print(countSetBits(n));
}
}// This code is contributed by
// Smitha Dinesh Semwal
Python3
# A simple program to count set bits
# in all numbers from 1 to n.# Returns count of set bits present in all
# numbers from 1 to n
def countSetBits(n):# initialize the result
bitCount = 0 for i in range ( 1 , n + 1 ):
bitCount + = countSetBitsUtil(i)return bitCount# A utility function to count set bits
# in a number x
def countSetBitsUtil(x):if (x <
= 0 ):
return 0
return ( 0 if int (x % 2 ) = = 0 else 1 ) +countSetBitsUtil( int (x / 2 ))# Driver program
if __name__ = = '__main__' :
n = 4
print ( "Total set bit count is" , countSetBits(n))# This code is contributed by
# Smitha Dinesh Semwal
C#
// A simple C# program to count set bits
// in all numbers from 1 to n.
using System;
class GFG
{
// Returns count of set bits present
// in all numbers from 1 to n
static int countSetBits( int n)
{
// initialize the result
int bitCount = 0;
for ( int i = 1;
i <
= n;
i++)
bitCount += countSetBitsUtil(i);
return bitCount;
}// A utility function to count set bits
// in a number x
static int countSetBitsUtil( int x)
{
if (x <
= 0)
return 0;
return (x % 2 == 0 ? 0 : 1) +
countSetBitsUtil(x / 2);
}// Driver program
public static void Main()
{
int n = 4;
Console.Write( "Total set bit count is " );
Console.Write(countSetBits(n));
}
}// This code is contributed by Sam007
的PHP
<
?php
// A simple program to count set bits
// in all numbers from 1 to n.// Returns count of set bits present
// in all numbers from 1 to n
function countSetBits( $n )
{
$bitCount = 0;
// initialize the resultfor ( $i = 1;
$i <
= $n ;
$i ++)
$bitCount += countSetBitsUtil( $i );
return $bitCount ;
}// A utility function to count
// set bits in a number x
function countSetBitsUtil( $x )
{
if ( $x <
= 0)
return 0;
return ( $x % 2 == 0 ? 0 : 1) +
countSetBitsUtil( $x / 2);
}// Driver Code
$n = 4;
echo "Total set bit count is " .
countSetBits( $n );
// This code is contributed by ChitraNayal
?>
输出如下:
Total set bit count is 5
【算法题(计算从1到n的所有数字中的总置位位数)】时间复杂度:O(nLogn)
方法2(比方法1简单高效)
如果我们从距离i的最右边观察到位, 则在垂直序列中2 ^ i位置后位会反转。
例如n = 5;
0 = 0000
1 = 0001
2 = 0010
3 = 0011
4 = 0100
5 = 0101
观察最右边的位(i = 0), 这些位在(2 ^ 0 = 1)之后翻转
观察最右边的第三位(i = 2), 这些位在(2 ^ 2 = 4)之后被翻转
因此, 我们可以垂直方式对位进行计数, 以便在第i个最右边的位置, 在2 ^ i次迭代后, 位将被翻转;
C ++
#include <
bits/stdc++.h>
using namespace std;
// Function which counts set bits from 0 to n
int countSetBits( int n)
{
int i = 0;
// ans store sum of set bits from 0 to n
int ans = 0;
// while n greater than equal to 2^i
while ((1 <
<
i) <
= n) {// This k will get flipped after
// 2^i iterations
bool k = 0;
// change is iterator from 2^i to 1
int change = 1 <
<
i;
// This will loop from 0 to n for
// every bit position
for ( int j = 0;
j <
= n;
j++) {ans += k;
if (change == 1) {
k = !k;
// When change = 1 flip the bit
change = 1 <
<
i;
// again set change to 2^i
}
else {
change--;
}
}// increment the position
i++;
}return ans;
}// Main Function
int main()
{
int n = 17;
cout <
<
countSetBits(n) <
<
endl;
return 0;
}
Java
public class GFG {// Function which counts set bits from 0 to n
static int countSetBits( int n)
{
int i = 0 ;
// ans store sum of set bits from 0 to n
int ans = 0 ;
// while n greater than equal to 2^i
while (( 1 <
<
i) <
= n) {// This k will get flipped after
// 2^i iterations
boolean k = false ;
// change is iterator from 2^i to 1
int change = 1 <
<
i;
// This will loop from 0 to n for
// every bit position
for ( int j = 0 ;
j <
= n;
j++) {if (k == true )
ans += 1 ;
else
ans += 0 ;
if (change == 1 ) {// When change = 1 flip the bit
k = !k;
// again set change to 2^i
change = 1 <
<
i;
}
else {
change--;
}
}// increment the position
i++;
}return ans;
}// Driver program
public static void main(String[] args)
{
int n = 17 ;
System.out.println(countSetBits(n));
}
}// This code is contributed by Sam007.
Python3
# Function which counts set bits from 0 to n
def countSetBits(n) :
i = 0# ans store sum of set bits from 0 to n
ans = 0# while n greater than equal to 2^i
while (( 1 <
<
i) <
= n) :# This k will get flipped after
# 2^i iterations
k = 0# change is iterator from 2^i to 1
change = 1 <
<
i# This will loop from 0 to n for
# every bit position
for j in range ( 0 , n + 1 ) :
ans + = kif change = = 1 :#When change = 1 flip the bit
k = not k# again set change to 2^i
change = 1 <
<
ielse :
change - = 1# increment the position
i + = 1return ans# Driver code
if __name__ = = "__main__" :n = 17
print (countSetBits(n))# This code is contributed by ANKITRAI1
C#
using System;
class GFG
{
static int countSetBits( int n)
{
int i = 0;
// ans store sum of set bits from 0 to n
int ans = 0;
// while n greater than equal to 2^i
while ((1 <
<
i) <
= n) {// This k will get flipped after
// 2^i iterations
bool k = false ;
// change is iterator from 2^i to 1
int change = 1 <
<
i;
// This will loop from 0 to n for
// every bit position
for ( int j = 0;
j <
= n;
j++) {if (k == true )
ans += 1;
else
ans += 0;
if (change == 1) {// When change = 1 flip the bit
k = !k;
// again set change to 2^i
change = 1 <
<
i;
}
else {
change--;
}
}// increment the position
i++;
}return ans;
}// Driver program
static void Main()
{
int n = 17;
Console.Write(countSetBits(n));
}
}// This code is contributed by Sam007
的PHP
<
?php
// Function which counts
// set bits from 0 to n
function countSetBits( $n )
{
$i = 0;
// ans store sum of set
// bits from 0 to n
$ans = 0;
// while n greater than
// equal to 2^i
while ((1 <
<
$i ) <
= $n )
{// This k will get flipped
// after 2^i iterations
$k = 0;
// change is iterator
// from 2^i to 1
$change = 1 <
<
$i ;
// This will loop from 0 to n
// for every bit position
for ( $j = 0;
$j <
= $n ;
$j ++)
{
$ans += $k ;
if ( $change == 1)
{
// When change = 1 flip
// the bit
$k = ! $k ;
// again set change to 2^i
$change = 1 <
<
$i ;
}
else
{
$change --;
}
}// increment the position
$i ++;
}return $ans ;
}// Driver code
$n = 17;
echo (countSetBits( $n ));
// This code is contributed by Smitha
?>
输出如下:
35
时间复杂度:O(k * n)
其中k =表示数字n的位数
k < = 64
方法3(整rick)
如果输入数的形式为2 ^ b -1, 例如1、3、7、15等, 则设置位数为b * 2 ^(b-1)。这是因为对于从0到(2 ^ b)-1的所有数字, 如果对列表进行补充和翻转, 则最终将得到相同的列表(位的一半打开, 一半关闭)。
如果数字没有全部设置位, 则某个位置m是最左边的设置位的位置。该位置的置位位数为n –(1 < < m)+1。其余的置位分为两部分:
1)(m-1)中的位向下定位到最左边的位变为0的点, 并且
2)该点以下的2 ^(m-1)数是上面的封闭形式。
一个简单的方法是考虑数字6:
0|0 0
0|0 1
0|1 0
0|1 1
-|--
1|0 0
1|0 1
1|1 0
最左边的置1位在位置2(位置从0开始)。如果我们掩盖掉剩下的是2(最后一行右侧的" 1 0"。)那么第二个位置(左下方的框)的位数是3(即2 + 1) 。 0-3(上面右上方的框)中的设置位是2 * 2 ^(2-1)=4。右下角的框是我们尚未计数的剩余位, 是设置的数量可以递归计算最多2个数字(右下方框中最后一个条目的值)的位数。
C ++
#include <
bits/stdc++.h>
// A O(Logn) complexity program to count
// set bits in all numbers from 1 to n
using namespace std;
/* Returns position of leftmost set bit.
The rightmost position is considered
as 0 */
unsigned int getLeftmostBit( int n)
{
int m = 0;
while (n >
1)
{
n = n >
>
1;
m++;
}
return m;
} /* Given the position of previous leftmost
set bit in n (or an upper bound on
leftmost position) returns the new
position of leftmost set bit in n */
unsigned int getNextLeftmostBit( int n, int m)
{
unsigned int temp = 1 <
<
m;
while (n <
temp) {
temp = temp >
>
1;
m--;
}
return m;
} // The main recursive function used by countSetBits()
unsigned int _countSetBits(unsigned int n, int m);
// Returns count of set bits present in
// all numbers from 1 to n
unsigned int countSetBits(unsigned int n)
{
// Get the position of leftmost set
// bit in n. This will be used as an
// upper bound for next set bit function
int m = getLeftmostBit(n);
// Use the position
return _countSetBits(n, m);
} unsigned int _countSetBits(unsigned int n, int m)
{
// Base Case: if n is 0, then set bit
// count is 0
if (n == 0)
return 0;
/* get position of next leftmost set bit */
m = getNextLeftmostBit(n, m);
// If n is of the form 2^x-1, i.e., if n
// is like 1, 3, 7, 15, 31, .. etc, // then we are done.
// Since positions are considered starting
// from 0, 1 is added to m
if (n == ((unsigned int )1 <
<
(m + 1)) - 1)
return (unsigned int )(m + 1) * (1 <
<
m);
// update n for next recursive call
n = n - (1 <
<
m);
return (n + 1) + countSetBits(n) + m * (1 <
<
(m - 1));
} // Driver code
int main()
{
int n = 17;
cout<
<
"Total set bit count is " <
<
countSetBits(n);
return 0;
} // This code is contributed by rathbhupendra
C
// A O(Logn) complexity program to count
// set bits in all numbers from 1 to n
#include <
stdio.h>
/* Returns position of leftmost set bit.
The rightmost position is considered
as 0 */
unsigned int getLeftmostBit( int n)
{
int m = 0;
while (n >
1) {
n = n >
>
1;
m++;
}
return m;
}/* Given the position of previous leftmost
set bit in n (or an upper bound on
leftmost position) returns the new
position of leftmost set bit in n*/
unsigned int getNextLeftmostBit( int n, int m)
{
unsigned int temp = 1 <
<
m;
while (n <
temp) {
temp = temp >
>
1;
m--;
}
return m;
}// The main recursive function used by countSetBits()
unsigned int _countSetBits(unsigned int n, int m);
// Returns count of set bits present in
// all numbers from 1 to n
unsigned int countSetBits(unsigned int n)
{
// Get the position of leftmost set
// bit in n. This will be used as an
// upper bound for next set bit function
int m = getLeftmostBit(n);
// Use the position
return _countSetBits(n, m);
}unsigned int _countSetBits(unsigned int n, int m)
{
// Base Case: if n is 0, then set bit
// count is 0
if (n == 0)
return 0;
/* get position of next leftmost set bit */
m = getNextLeftmostBit(n, m);
// If n is of the form 2^x-1, i.e., if n
// is like 1, 3, 7, 15, 31, .. etc, // then we are done.
// Since positions are considered starting
// from 0, 1 is added to m
if (n == ((unsigned int )1 <
<
(m + 1)) - 1)
return (unsigned int )(m + 1) * (1 <
<
m);
// update n for next recursive call
n = n - (1 <
<
m);
return (n + 1) + countSetBits(n) + m * (1 <
<
(m - 1));
}// Driver program to test above functions
int main()
{
int n = 17;
printf ( "Total set bit count is %d" , countSetBits(n));
return 0;
}
Java
// Java A O(Logn) complexity program to count
// set bits in all numbers from 1 to n
import java.io.*;
class GFG
{/* Returns position of leftmost set bit.
The rightmost position is considered
as 0 */
static int getLeftmostBit( int n)
{
int m = 0 ;
while (n >
1 )
{
n = n >
>
1 ;
m++;
}
return m;
} /* Given the position of previous leftmost
set bit in n (or an upper bound on
leftmost position) returns the new
position of leftmost set bit in n */
static int getNextLeftmostBit( int n, int m)
{
int temp = 1 <
<
m;
while (n <
temp)
{
temp = temp >
>
1 ;
m--;
}
return m;
} // The main recursive function used by countSetBits()
// Returns count of set bits present in
// all numbers from 1 to n static int countSetBits( int n)
{
// Get the position of leftmost set
// bit in n. This will be used as an
// upper bound for next set bit function
int m = getLeftmostBit(n);
// Use the position
return countSetBits(n, m);
} static int countSetBits( int n, int m)
{
// Base Case: if n is 0, then set bit
// count is 0
if (n == 0 )
return 0 ;
/* get position of next leftmost set bit */
m = getNextLeftmostBit(n, m);
// If n is of the form 2^x-1, i.e., if n
// is like 1, 3, 7, 15, 31, .. etc, // then we are done.
// Since positions are considered starting
// from 0, 1 is added to m
if (n == (( int ) 1 <
<
(m + 1 )) - 1 )
return ( int )(m + 1 ) * ( 1 <
<
m);
// update n for next recursive call
n = n - ( 1 <
<
m);
return (n + 1 ) + countSetBits(n) + m * ( 1 <
<
(m - 1 ));
} // Driver code
public static void main (String[] args)
{int n = 17 ;
System.out.println ( "Total set bit count is " + countSetBits(n));
}
}// This code is contributed by ajit..
Python3
# A O(Logn) complexity program to count
# set bits in all numbers from 1 to n"""
/* Returns position of leftmost set bit.
The rightmost position is considered
as 0 */
"""
def getLeftmostBit(n):m = 0
while (n >
1 ) :n = n >
>
1
m + = 1return m"""
/* Given the position of previous leftmost
set bit in n (or an upper bound on
leftmost position) returns the new
position of leftmost set bit in n */
"""
def getNextLeftmostBit(n, m) :temp = 1 <
<
m
while (n <
temp) :
temp = temp >
>
1
m - = 1return m# The main recursive function used by countSetBits()
# def _countSetBits(n, m)# Returns count of set bits present in
# all numbers from 1 to n
def countSetBits(n) :# Get the position of leftmost set
# bit in n. This will be used as an
# upper bound for next set bit function
m = getLeftmostBit(n)# Use the position
return _countSetBits(n, m)def _countSetBits(n, m) :# Base Case: if n is 0, then set bit
# count is 0
if (n = = 0 ) :
return 0# /* get position of next leftmost set bit */
m = getNextLeftmostBit(n, m)# If n is of the form 2^x-1, i.e., if n
# is like 1, 3, 7, 15, 31, .. etc, # then we are done.
# Since positions are considered starting
# from 0, 1 is added to m
if (n = = ( 1 <
<
(m + 1 )) - 1 ) :
return ((m + 1 ) * ( 1 <
<
m))# update n for next recursive call
n = n - ( 1 <
<
m)
return (n + 1 ) + countSetBits(n) + m * ( 1 <
<
(m - 1 ))# Driver code
n = 17
print ( "Total set bit count is" , countSetBits(n))# This code is contributed by rathbhupendra
C#
// C# A O(Logn) complexity program to count
// set bits in all numbers from 1 to n
using System;
class GFG
{/* Returns position of leftmost set bit.
The rightmost position is considered
as 0 */
static int getLeftmostBit( int n)
{
int m = 0;
while (n >
1)
{
n = n >
>
1;
m++;
}
return m;
} /* Given the position of previous leftmost
set bit in n (or an upper bound on
leftmost position) returns the new
position of leftmost set bit in n */
static int getNextLeftmostBit( int n, int m)
{
int temp = 1 <
<
m;
while (n <
temp)
{
temp = temp >
>
1;
m--;
}
return m;
} // The main recursive function used by countSetBits()
// Returns count of set bits present in
// all numbers from 1 to n
static int countSetBits( int n)
{
// Get the position of leftmost set
// bit in n. This will be used as an
// upper bound for next set bit function
int m = getLeftmostBit(n);
// Use the position
return countSetBits(n, m);
} static int countSetBits( int n, int m)
{
// Base Case: if n is 0, // then set bit count is 0
if (n == 0)
return 0;
/* get position of next leftmost set bit */
m = getNextLeftmostBit(n, m);
// If n is of the form 2^x-1, i.e., if n
// is like 1, 3, 7, 15, 31, .. etc, // then we are done.
// Since positions are considered starting
// from 0, 1 is added to m
if (n == (( int )1 <
<
(m + 1)) - 1)
return ( int )(m + 1) * (1 <
<
m);
// update n for next recursive call
n = n - (1 <
<
m);
return (n + 1) + countSetBits(n) +
m * (1 <
<
(m - 1));
} // Driver code
static public void Main ()
{
int n = 17;
Console.Write( "Total set bit count is " +
countSetBits(n));
}
}// This code is contributed by Tushil.
输出如下:
Total set bit count is 35
时间复杂度:O(Logn)。从实现的第一眼看, 时间复杂度看起来更多。但是, 如果我们仔细研究一下, 则将对n中的所有0位执行getNextLeftmostBit()的while循环内的语句。并且执行递归的次数小于或等于n中的设置位。换句话说, 如果控件进入getNextLeftmostBit()的while循环内部, 则它将跳过递归的许多位。
感谢agatsu和IC提出此解决方案。
这是另一种建议的解决方案皮尤什·卡普尔(Piyush Kapoor).
一个简单的解决方案, 使用以下事实:对于第i个最低有效位, 答案为
(N/2^i)*2^(i-1)+ X
其中
X = N%(2^i)-(2^(i-1)-1)
iff
N%(2^i)>
=(2^(i-1)-1)
int getSetBitsFromOneToN( int N){
int two = 2, ans = 0;
int n = N;
while (n){
ans += (N/two)*(two>
>
1);
if ((N&
(two-1)) >
(two>
>
1)-1) ans += (N&
(two-1)) - (two>
>
1)+1;
two <
<
= 1;
n >
>
= 1;
}
return ans;
}
如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请发表评论。
推荐阅读
- 凯捷面试经验分享|校园2019
- u盘损坏如何修好,本文教您u盘损坏如何修好
- 超微 bios设置,本文教您超微主板bios怎样设置U盘打开
- u盘查杀,本文教您u盘怎样查杀病毒
- 惠普u盘打开,本文教您惠普笔记本怎样设置u盘打开
- win10之家,本文教您怎样运用U盘重装win10系统
- U盘系统_本文教您将系统安装到U盘
- 昂达u盘打开,本文教您昂达主板BIOS怎样设置u盘打开
- usb鼠标接触不良,本文教您usb鼠标接触不良