给定数字范围[a,b],如何有效地找到此范围内所有数字的按位OR。为范围[a,b]运行循环并单独计算所有数字的按位OR对于非常大的范围来说太耗时,所以这不是选项。
答案 0 :(得分:4)
任何数量的形式2 n -1将是n
1的位模式。当你对它下面的任何数字进行OR运算时,得到2 n -1。因此,可以忽略范围内最高2 n -1以下的所有数字。
范围中的下一个数字将是1
,后跟n
0
s,当您与此进行OR时,您将获得n+1
{{1} }秒。由于我们选择上述数字作为2的最大功率,我们将永远不会再获得该数字的位数。
所以基本上只有2个案例。如果范围的顶部是2 n -1,则结果是具有1
n
位的数字。否则它是1
1位。
以上假设范围包括2 n -1值。如果没有,只需尝试循环(可能会进行一些优化,但我无法想到它们。)
答案 1 :(得分:2)
而不是为所有数字执行此操作,您可以为所有位置执行此操作。这将只需要log(n)步骤。
所以让我们试着想象 - 单位何时会是1?如果上限或下限是奇数或者它们之间有一个数字。所以要么降低%2 == 1或更低!=更高。
很棒,我们有单位。现在如果从上部和下部位移除较低的一位并重复,我们得到其他位置。
只有特殊情况,如果更低==更高。在那种情况下,我们返回下层。
以下是代码 -
unsigned int bitwiseor(unsigned int a, unsigned int b){
if (a==b)
return a;
unsigned final = 0;
unsigned rev = 0;
while(b){
final*=2;
if (a%2==1 || a != b)
final++;
a/=2;
b/=2;
}
while(final){
rev *= 2;
rev += final % 2;
final/=2;
}
return rev;
}
第二个循环是保留位序列。
在这里演示 - https://ideone.com/MCIugW
感谢@Meixner提供的驱动程序代码。
答案 2 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
int dumb(int a, int b)
{
int z=0;
while(a<=b) z|=a++;
return z;
}
int smart(int a, int b)
{
int d,z;
if(a>b) return 0;
d=b-a+1;
z=0;
while(d>1) { z=(z<<1)|1; d>>=1; }
d=z;
z|=a;
a+=d;
while(a<=b) z|=a++;
return z;
}
int main(int argc, char *argv[])
{
int a,b;
for(a=0;a<1000;a++) {
for(b=a;b<1000;b++) {
int z1=dumb(a,b);
int z2=smart(a,b);
if(z1!=z2) {
printf("fail %d %d\n",a,b);
}
}
}
return 0;
}