升读A遵循以下规则:
每个值都是加在一起直到并包括N sub i的所有奇数值。
N sub 4。
1+3+5+7 = 16
升读B遵循此规则。 取平方根的上限乘以2加1.从天花板上减去N.继续添加奇数。
N = 33
天花板(√33)= 6
6 * 2 + 1 = 13。
36-33 = 3。
3 + 13 = 16。
停止为16在进展A和B中都可以快速执行此操作吗?即最小的1步或2步解决方案?一个java或一般实现将是方便的
* 问题*
What is the output you desire? Simply abool saying they do meet? Or do you want the indices at which they do meet, i.e.A[4]=16 andB[17]=16? Or do you just want the number at which they meet, i.e.16? And what if they don't meet exactly? Do you want the indices (or number) before, or after, the intersection? Finally, when or how do you decide to halt, if, say, the two sequences will never meet? (I know in this case they do, but I mean in the general case.)
我期望的输出将是值16,或者它可以是B找到值的索引,因为两者都是等价的,因为索引只是第i个术语。如果他们不见面,我意识到这是一个非终止程序。这种情况我不在乎。
答案 0 :(得分:4)
我会在这里总结一下我的评论,以便更容易理解新访问者。
正如其他人所指出的,序列A 仅仅是一系列正方形;通过他的评论澄清了OP,序列B 将不断变化。
重述OP的问题可能是
是否有更快的方法来确定递增序列中的第一个方块,而不是计算序列的每个项?
确实有。显而易见的想法是设计一种方法来“跳过”某些术语的计算,基于对正方形增长率和序列的洞察力。但是很难以编程方式得出有关任意序列的见解。
更强大的解决方案可能是将问题重新表述为找到最小的零点:
B(x) - x^2 = 0
为此,可能存在可能有帮助的root-finding algorithms。如果您不需要找到最小零,那么更容易:实现任何根查找算法,观察算法收敛到零,添加x^2
以补偿重构,你有它。
修改强>
(评论框太有限了,无法回复你的。)
当我说“二分”时,我实际上是指“二分搜索”。这需要一个上限,因此不适用于您的问题。
让我提供一个天真的算法,但作为一个开始,虽然你可能已经考虑过这个。
B(1)
。说它是1692
(不是正方形)。B(2)
。说它是1707
(不是正方形)。B(2)-B(1)
,将其称为“delta”,例如 1707-1692
或15
。考虑这是B
增长率的天真估计。当然,这几乎肯定是错的,但我们所有的目标都是某种方式来跳过术语。这就是后来要优化的内容。1707
的是什么?公式(floor(sqrt(1707))+1)^2
会产生1764
。(1764-1707)/15
会产生3.8
,我们可以将其舍入4
。B(2+4) = B(6)
。
1764
,那么您需要继续前进。但在这种情况下,你已经保存了3个术语。你究竟如何选择继续前进,只是另一种选择。您可以计算B(7)
并转到第3步(将B(7)-B(6)
计算为新增量)。您可以直接转到第3步(将(B(6)-B(2))/4
计算为新增量)。 (如果没有表征 B
的可能功能,你真的不知道什么是最好的。)1764
,那么您需要返回。同样,有很多方法。二进制搜索实际上是一种简单,合理的方式。计算B(4)
,因为它直接位于B(2)
和B(6)
之间。如果小于1764
,请尝试B(5)
。如果大于1764
,请尝试B(3)
。如果两者不匹配,则从B(7)
开始继续。使用二进制搜索,您最多可以进行log(N)
次计算。这听起来很划算,对吗?你要么跳过很多计算,要么最多只做log(N)
。 (或者,你会发现更好的优化。)但是,显然,它并不那么简单,因为你正在做额外的计算来找到这些增量,投影,二分搜索等等。因为正方形增长非常缓慢(只有如果你处理的是大整数,或者B
的极其复杂的序列,我认为这样的算法只能击败“线性搜索”(计算每个术语)(但是给定B
1}}必须总是增加,序列真正有多复杂?)关键是要找到适合所有序列的特征,并利用 by找到特定于它的优化。
我仍然不知道您的应用程序是什么,但此时您可能只是尝试它并在真实数据集上对其进行基准测试(与线性搜索相比)。这将立即告诉您是否有任何实际收益,以及是否应该投入更多时间进行优化。它会比尝试所有理论数学,表征序列等等更快。
答案 1 :(得分:1)
仅供参考,您的第一个序列就是方块。
应该清楚,两个序列都是单调递增的。因此,您需要做的就是在每个序列中保留一个索引,并反复将任何索引点增加到一个较小的数字,直到两个索引指向相同的数字。
请注意,如果序列没有共同的数字,这将永远运行。
答案 2 :(得分:0)
伪码中的算法:
int i=1, j=1;
int x=func1(i), y=func2(j);
while x!=y {
if x<y {i++; x=func1(i)}
else {j++; y=func2(j)}
}
假设我们所知道的是func1
和func2
正在增加函数,则很难进一步优化此算法。