编写一个算法来查找F(n)
设置为1的位数,对于任何给定的n值,所有数字都从1到n。
复杂性应为O(log n)
例如:
1: 001
2: 010
3: 011
4: 100
5: 101
6: 110
所以
F(1) = 1,
F(2) = F(1) + 1 = 2,
F(3) = F(2) + 2 = 4,
F(4) = F(3) + 1 = 5,
etc.
我只能设计O(n)
算法。
答案 0 :(得分:39)
解决这些问题的方法是写出前几个值,并寻找一个模式
Number binary # bits set F(n) 1 0001 1 1 2 0010 1 2 3 0011 2 4 4 0100 1 5 5 0101 2 7 6 0110 2 9 7 0111 3 12 8 1000 1 13 9 1001 2 15 10 1010 2 17 11 1011 3 20 12 1100 2 22 13 1101 3 25 14 1110 3 28 15 1111 4 32
需要一点盯着看,但有些人认为你注意到前8个和后8个数字的二进制表示是完全相同的,除了前8个在MSB中有一个0
(最高位),而最后8位有1
。因此,例如,为了计算F(12)
,我们可以取F(7)
并在其中添加8,9,10,11和12中的设置位数。但是这与集合的数量相同-bits在0,1,2,3和4 (即F(4)
)中,每个数字再加一个!
# binary 0 0 000 1 0 001 2 0 010 3 0 011 4 0 100 5 0 101 6 0 110 7 0 111 8 1 000 <--Notice that rightmost-bits repeat themselves 9 1 001 except now we have an extra '1' in every number! 10 1 010 11 1 011 12 1 100
因此,对于8 <= n <= 15
,F(n) = F(7) + F(n-8) + (n-7)
。同样,我们可以注意到4 <= n <= 7
,F(n) = F(3) + F(n-4) + (n-3)
;以及2 <= n <= 3
,F(n) = F(1) + F(n-2) + (n-1)
。一般来说,如果我们设置a = 2^(floor(log(n)))
,那么F(n) = F(a-1) + F(n-a) + (n-a+1)
这并没有给我们一个O(log n)
算法;但是,这样做很容易。如果a = 2^x
,请在上表中注明,对于a-1
,第一位设置为a/2
次,第二位设置为a/2
次,第三位......一直到第x位。因此,F(a-1) = x*a/2 = x*2^(x-1)
。在上面的等式中,这给了我们
F(n) = x*2x-1 + F(n-2x) + (n-2x+1)
x = floor(log(n))
。计算F
的每次迭代都将基本上删除MSB;因此,这是一个O(log(n))
算法。
答案 1 :(得分:7)
如果n= 2^k-1, then F(n)=k*(n+1)/2
对于一般n
,让m
成为m = 2^k-1
和m<=n
的最大数字。 F(n) = F(m) + F(n-m-1) + (n-m)
。
转弯条件:F(0)=0
和F(-1)=0
。
答案 2 :(得分:4)
考虑以下内容:
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
如果要查找从1到14的总设置位数(1110) 几点观察:
0th
位(LSB)1
位每两位出现一次(参见垂直方向),因此设置位数= n/2 +
1
如果n's 0th bit is 1
否则0
)1st
位位置= (n/4 *2) + 1
中的设置位数(因为1st
位是一个集合,否则为0
)2nd
位:4
连续1s
出现在每个8
位(这个有点棘手)
第二个位置的设置位数= (n/8*4 )+ 1
(因为设置了2nd
位,否则为0
)+ ((n%8)%(8/2))
最后一项是包括1s
位前(n/8)
位组14/8 =1
的数量1
仅考虑4
组,即。8
设置位1s
位。我们需要包含14-8 = 6
位中找到的3rd
8
位:每16
位出现3rd
个连续1位(与上面类似)
(n/16*8)+1
位置= 3rd
中的设置位数(自0
位开始设置,否则+ ((n%16)%(16/2))
)O(1)
所以我们对n
的每个位进行log2(n)
计算。
数字包含n
位。因此,当我们对O(logn)
的所有位置进行上述迭代并在每一步添加所有设置位时,我们会在{{1}}步骤中得到答案
答案 3 :(得分:3)
快速搜索序列F的值会导致此整数序列 http://oeis.org/A000788
在那里我发现了一个公式: a(0)= 0,a(2n)= a(n)+ a(n-1)+ n,a(2n + 1)= 2a(n)+ n + 1(a与F相同,因为我只需从oeis复制公式)
可用于计算log(n)中的(n)。
这是我的示例C ++代码:
memset(cache, -1, sizeof(cache))
cache[0] = 0
int f(int n)
if cache[n] != -1 return cache[n];
cache[n] = n % 2 ? (2 * f(n / 2) + n / 2 + 1) : (f(n / 2) + f(n / 2 - 1) + n / 2)
答案 4 :(得分:3)
这是我的解决方案。时间复杂度:O(Log n)
public int countSetBits(int n){
int count=0;
while(n>0){
int i= (int)(Math.log10(n)/Math.log10(2));
count+= Math.pow(2, i-1)*i;
count+= n-Math.pow(2, i)+1;
n-= Math.pow(2, i);
}
return count;
}
答案 5 :(得分:2)
设k
为n
所需的位数。
对于0,...,2^(k-1)-1
,每个位的数字正好是一半,所以到目前为止我们有(k-1)*2^(k-1)/2 = (k-1)*2^(k-2)
位。我们只需要查看大于2^(k-1)-1
的数字的内容
对于MSB,我们也有n-2^(k-1)-1
位“up”。
所以我们可以推导出递归函数:
f(n) = (k-1)*2^(k-2) + n-(2^(k-1)-1) + f(n-(2^(k-1)))
^ ^ ^
first MSBs recursive call for
2^(k-1)-1 n-2^(k-1) highest numbers
numbers
其中base为f(0) = 0
和f(2^k) = k*2^(k-1) + 1
[正如我们之前看到的那样,我们确切知道2^(k-1)-1
的位数是多少,我们只需要为MSB添加1 - 2^k
]
由于发送到f
的值在每次迭代时减少了至少一半,因此总计O(logn)
答案 6 :(得分:2)
使用带位掩码的DP可以解决此问题。
自下而上方法背后的基本直觉是,我们将直接访问具有值current_number / 2的数字中的设置位数,并且我们还将检查是否仅在此current_number中设置了最后一位用1.进行操作。
current_number / 2或current_number >> 1基本上删除了此current_number的最后一位,因此为了将该位包括在我们的计数中,我们必须使用&操作手动检查此数字的最后一位。
这是用于计算数字i中的设置位数的表达式 dp [i] = dp [i >> 1] +(i&1)
如果您在解决此问题时仍然感到困惑,则可以参考以下视频以获得更好的解释:-
答案 7 :(得分:1)
简短又甜蜜!
public static int countbits(int num){
int count=0, n;
while(num > 0){
n=0;
while(num >= 1<<(n+1))
n++;
num -= 1<<n;
count += (num + 1 + (1<<(n-1))*n);
}
return count;
}//countbis
答案 8 :(得分:0)
这是java函数
private static int[] findx(int i) {
//find the biggest power of two number that is smaller than i
int c = 0;
int pow2 = 1;
while((pow2<< 1) <= i) {
c++;
pow2 = pow2 << 1;
}
return new int[] {c, pow2};
}
public static int TotalBits2(int number) {
if(number == 0) {
return 0;
}
int[] xAndPow = findx(number);
int x = xAndPow[0];
return x*(xAndPow[1] >> 1) + TotalBits2(number - xAndPow[1]) + number - xAndPow[1] + 1;
}
答案 9 :(得分:0)
这是用java编码的...
逻辑:说数字是34,二进制等于蚂蚁是10010,可以写成10000 + 10。
10000有4个零,因此在此数字之前的所有1的计数是2 ^ 4(原因如下)。所以计数是2 ^ 4 + 2 ^ 1 + 1(自己编号)。所以答案是35
*对于二进制数10000.填充4个位置的总组合为2 * 2 * 2 * 2x2(一或零)。因此,1的总组合是2 * 2 * 2 * 2.
public static int getOnesCount(int number) {
String binary = Integer.toBinaryString(number);
return getOnesCount(binary);
}
private static int getOnesCount(String binary) {
int i = binary.length();
if (i>0 && binary.charAt(0) == '1') {
return gePowerof2(i) + getOnesCount(binary.substring(1));
}else if(i==0)
return 1;
else
return getOnesCount(binary.substring(1));
}
//can be replaced with any default power function
private static int gePowerof2(int i){
int count = 1;
while(i>1){
count*=2;
i--;
}
return count;
}
答案 10 :(得分:0)
顺便说一句,这个问题也可以通过查找表的方法来完成。预先计算0-255的设置位数并存储它。发布,我们可以通过将给定数字分成两部分,每部分8位来计算任何数字中的设置位数。对于每个部分,我们可以在第一步中形成的count数组中查找。例如,如果有一个16位数字,如
x = 1100110001011100
,这里,设置位数=第一个字节中的设置位数+第二个字节中的设置位数。因此,为获得第一个字节,
y = (x & 0xff)
z = (x >> 8) & (0xff)
total set bits = count[y] + count[z]
此方法也将在O(n)中运行。
答案 11 :(得分:0)
不确定是否迟到了回复,但这是我的调查结果。
尝试用以下方法解决问题,对于数字N每个bitno(从LSB到MSB,比如LSB以bitno 1开始并且用下一个比特值递增)设置的位数可以被计算为,(N /(2 topower) bitno)*(2 topower bitno-1)+ {(N%(2 topower bitno)) - [(2 topower bitno-1) - 1]}
为它编写递归函数C / C ++请检查。我不确定,但我认为它的复杂性是log(N)。传递函数2参数,我们想要计算位数的数字(no)和LSB的第二个开始计数,值为1.
int recursiveBitsCal(int no, int bitno){
int res = int(no/pow(2,bitno))*int(pow(2,bitno-1));
int rem1 = int(pow(2,bitno-1)) -1;
int rem = no % int(pow(2,bitno));
if (rem1 < rem) res += rem -rem1;
if ( res <= 0 )
return 0;
else
return res + recursiveBitsCal(no, bitno+1);
}
答案 12 :(得分:0)
for i in range(int(input())):
n=int(input())
c=0
m=13
if n==0:
print(c)
while n%8!=0 or n!=0:
t=bin(n)[2:]
c+=t.count('1')
n=n-1
if n!=0:
j=n//8
if j==1:
c+=m
else:
c+=m+((j-1)*7)
print(c)
答案 13 :(得分:0)
**// 1. Check database version:**
private Boolean checkDataBaseVersion() {
Boolean Upgrade = false;
SQLiteDatabase db = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
Integer CurrentdbVersion = db.getVersion();
if (CurrentdbVersion < DATABSE_VERSION) {
Upgrade = true;
} else {
Upgrade = false;
}
Log.w("POSITIVE ...", "checkDataBase - Database Upgrade = " + Upgrade + " ... CurrentdbVersion: "
+ CurrentdbVersion + " DATABSE_VERSION: " + DATABSE_VERSION);
db.close();
return Upgrade;
}
**// 2. change copy database code:**
public void copyDataBase() {
if (!checkDataBase()) {
this.getReadableDatabase();
this.close();
try {
copyDBFile();
Log.w("POSITIVE ...", "copyDataBase - Database does not exists ... db copied");
} catch (IOException mIOException) {
throw new Error("حدث خطأ في نسخ قاعدة البانات من الملف");
}
} else if (checkDataBaseVersion()) {
//this.getReadableDatabase();
//this.close();
try {
copyDBFile();
Log.w("POSITIVE ...", "copyDataBase - Database exists - new version exists ... db copied ");
} catch (IOException mIOException) {
throw new Error("حدث خطأ في نسخ قاعدة البانات من الملف");
}
} else {
Log.w("POSITIVE ...", "copyDataBase - Database exists - no new version ... nothing done ");
}
}
private boolean checkDataBase() {
File dbFile = new File(DATABASE_LOCATION + DATABASE_NAME);
Log.w("POSITIVE ...", "checkDataBase - Database exists = " + dbFile.exists());
close(); /// NEW
return dbFile.exists();
}
**// 3. remove copy database code from public QuizDbHelper(Context context) and place it where it is needed:**
public QuizDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABSE_VERSION);
if (android.os.Build.VERSION.SDK_INT >= 17)
DATABASE_LOCATION = context.getApplicationInfo().dataDir + "/databases/";
else
DATABASE_LOCATION = "/data/data/" + context.getPackageName() + "/databases/";
this.mContext = context;
}
请查看我在geeksforgeeks.org上的文章,以获取详细说明。 以下是文章的链接 https://www.geeksforgeeks.org/count-total-set-bits-in-all-numbers-from-1-to-n-set-2/
答案 14 :(得分:0)
我知道这则帖子迟到了,请在下面找到logn
解决方案:
static int countSetBitWithinRange(int n)
{
int x = n + 1, index = 0, count = 0;
int numberOfOnesInAGroup = (int)Math.pow(2, index);
while(x >= numberOfOnesInAGroup)
{
int countOfZeroOnePairs = (x / numberOfOnesInAGroup);
int numberOfPairsOfZerosAndOnes = countOfZeroOnePairs / 2;
int numberOfSetBits = numberOfPairsOfZerosAndOnes * numberOfOnesInAGroup;
//If countOfZeroOnePairs is even then the pairs are complete else there will be ones that do not have a corresponding zeros pair
int remainder = (countOfZeroOnePairs % 2 == 1) ? (x % numberOfOnesInAGroup) : 0;
count = count + numberOfSetBits + remainder;
numberOfOnesInAGroup = 1 << ++index;
}
return count;
}
答案 15 :(得分:-1)
x = int(input("Any number:\n"))
y = (bin(x))
print(y)
v = len(y) -2
print(v)