我们有两个N位数(0 set_a idx x:将A [idx]设置为x,其中0 <= idx&lt; N,其中A [idx]是A的最低有效位。 set_b idx x:将B [idx]设置为x,其中0 <= idx&lt; Ñ get_c idx:打印C [idx],其中C = A + B,0 <= idx 现在,我已经尽可能地优化了代码。 首先,我尝试使用int数组来表示a,b和c。对于每次更新,我计算c并在查询时返回第i位。这很慢。仅清除4/11测试用例。 我转而使用布尔数组。它比int数组方法快2倍左右。清除7/11测试用例。 接下来,我发现我不需要计算c来计算A + B的idx位。我将从idx向右扫描A和B,直到找到[i] = b [i] = 0或a [i] = b [i] = 1。如果a [i] = b [i] = 0,那么我只是向左加到idx th bit,从初始进位= 0开始。如果a [i] = b [i] = 1,那么我只是从左边加到idx,从初始进位= 1开始。
这更快,但只清除了8/11个测试用例。 然后,我想出一次,我到了位置i,a [i] = b [i] = 0或a [i] = b [i] = 1,然后我不需要加起来朝着idx的位置。如果a [i] = b [i] = 0,那么答案是(a [idx] + b [idx])%2,如果a [i] = b [i] = 1,那么答案是(a [ IDX] + b [IDX] 1)%2。它的速度提高了大约40%,但仍然只清除了8/11个测试用例。 现在我的问题是如何降低这3个''硬'的测试用例?我不知道它们是什么,但程序花了> 3秒来解决问题。 以下是代码:http://ideone.com/LopZf
答案 0 :(得分:0)
一种可能的优化是替换
(a[pos]+b[pos]+carry)%2
与
a[pos]^b[pos]^carry
XOR运算符(^)执行加法模2,使得可能不需要昂贵的mod运算(%)。根据语言和编译器的不同,编译器可能会在执行功率为2的mod时为您进行优化。但是,由于您是微优化,因此只需进行一项简单的更改即可消除对优化后的优化。场景。
http://en.wikipedia.org/wiki/Exclusive_or
这只是一个简单易懂的建议。正如其他人所建议的那样,使用压缩的int来表示你的位数组也可能会改善你的代码最糟糕的情况。这将是最高有效位的get_c函数,其中A或B(但不是两者)对于所有其他位置为1,需要将每个位位置扫描到最低有效位以确定进位。如果您使用压缩的int作为比特,那么只需要大约1/32的操作(假设32位整数)。然而,使用压缩的int比使用简单的布尔数组(实际上可能只是一个字节数组)要复杂得多。
Convert bit array to uint or similar packed value
http://en.wikipedia.org/wiki/Bit_array
Stackoverflow和net上有很多其他的例子,就像使用int数组一样。
答案 1 :(得分:0)
这是一个看起来有点算法的解决方案。我用字节来演示它,但当然你可以使用32位字轻松优化算法(我想你的机器现在有64位算术)。
void setbit( unsigned char*x,unsigned int idx,unsigned int bit)
{
unsigned int digitIndex = idx>>3;
unsigned int bitIndex = idx & 7;
if( ((x[digitIndex]>>bitIndex)&1) ^ bit) x[digitIndex]^=(1u<<bitIndex);
}
unsigned int getbit(unsigned char *a,unsigned char *b,unsigned int idx)
{
unsigned int digitIndex = idx>>3;
unsigned int bitIndex = idx & 7;
unsigned int c = a[digitIndex]+b[digitIndex];
unsigned int bit = (c>>bitIndex) & 1;
/* a zero bit on the right will absorb a carry, let's check if any */
if( (c^(c+1))>>bitIndex )
{
/* none, we must check if there's a carry propagating from the right digits */
for(;digitIndex-- > 0;)
{
c=a[digitIndex]+b[digitIndex];
if( c > 255 ) return bit^1; /* yes, a carry */
if( c < 255 ) return bit; /* no carry possible, a zero bit will absorb it */
}
}
return bit;
}
如果你发现任何神秘的东西,请问。 编辑:oops,我将零位条件反转......