我有一个在O(end-start)中运行的循环,我想用O(1)替换它。
如果“宽度”不会减少,那将非常简单。
for (int i = start; i <= end; i++, width--)
if (i % 3 > 0) // 1 or 2, but not 0
z += width;
开始,结束和宽度具有正值
答案 0 :(得分:2)
请注意
width == initial_width - (i - start)
所以求和可以改写为
end
—————
\ (initial_width + start - i)
/
—————
i=start
i mod 3 ≠ 0
end ⌊end/3⌋
————— —————
== \ (initial_width + start - i) —— \ (initial_width + start - 3j)
/ /
————— —————
i=start j=⌈start/3⌉
其余的应该很简单。
答案 1 :(得分:2)
正如其他人提到的,这可能是最容易被认为是两个系列的总和。
x x+3 x+6 ... x+3N
+ x+3N x+3(N-1) x+3(N-2) ... x
-----------------------------------
2x+3N 2x+3N 2x+3N ... 2x+3N
以上可以简化为 (2X + 3N)(N + 1)
这意味着其中一个的总和真的...... (2X + 3N)(N + 1)/ 2
这个等式需要适用于两个系列。两者的N可能不同。
因此,您所要做的就是确定您的起点和系列中的项目数。这应留给学生练习。
希望这有帮助。
答案 2 :(得分:1)
将这视为两个单独系列的总和可能最容易,一个用于i%3 = 1
,另一个用于i%3=2
。或者,您可以将其视为i
的所有值减去i%3=0
的总和的总和。为了论证,让我们看看后一种方法的前半部分:总结所有宽度值。
在这种情况下,width
将从某个初始值开始,每次迭代其值将减少1.在最后一次迭代中,其值将减少(end-start)
。也许最容易将其视为三角形。为了简单起见,我们将使用较小的数字 - 我们将从width = 5,start = 1和end = 5开始。也许最简单的绘制图表:
宽度值:
*
**
***
****
*****
我们真正想要的是那个三角形的面积 - 这是一个非常着名的基本几何公式 - 1 / 2ab,其中a和b是两边的长度(在这种情况下) ,由width
和end-start
的初始值定义。这假设它确实是一个三角形 - 即它减少到0.实际上,我们很有可能处理一个截断的三角形 - 但其公式也是众所周知的(1 / 2a < sub> 1 b + 1 / 2a 2 b,其中a是右侧和左侧的高度,b是宽度。
答案 3 :(得分:1)
我想出了这个丑陋的方法:
int start; // = some number
int end; // = ...
int initialwidth; // = ...
int each = (end+1)/3 - (start-1)/3 - 1;
int loop = 2*(3-(start+2)%3)+1;
int total = each*loop + 3*each*(each-1) + (start%3==1) + (end-start)*(end%3==1);
int result = -total + initialwidth*(1 + end - start - end/3 + (start-1)/3);
总计将给出i =开始结束时(i%3> 0)的总和(i-start)s。
结果将给出添加到z的宽度总和。
答案 4 :(得分:1)
和(i = 1 ... n)i的闭合形式是(n)(n + 1)/ 2。你应该可以用一个小代数来找到一个封闭的表格,为你提供你正在寻找的结果。
答案 5 :(得分:0)
你想要像z = 2 * width * (start - end) / 3 + (start - end) % 3
这样的东西吗? (不太对,但足够接近让你走上正确的轨道。
答案 6 :(得分:0)
这不是一个完整的答案,但你应该注意到:
x = end - start;
k = ~(-1 << x); // I think (width * k)>>x would be your z except if you didn't have the contidional
并且从LSB向上设置两个位,一位清零,两位设置,一位清零(0x ... 011011011)的值可用于计算%3为0的位置。
R = k - (k & 0x...011011011); // This is the series 3 + (3 << 3) + (3 << 6) ...
z = (R * width)>>x; // I think.
只是尝试一下。我可能犯了一些错误。