昨天我上的算法测试这个问题,我想不出答案。 这是推动我绝对是疯了,因为它是价值约40分。 我想,大多数类的没有正确地解决它,因为我还没有想出了在过去24小时内解决。
给定长度为n的任意的二进制字符串,查找字符串中的三个间隔均匀的,如果存在的话。 写这解决了这个在O(N *的log(n))时间的算法。
所以像这些字符串被“均匀分布的”三个一:11100000,0100100100
编辑:这是一个随机数,所以它应该是能够为任意数量的工作。 我给的例子是为了说明“均匀间隔”属性。 所以,1001011是一个有效的数字。 用1,图4和7之处在于均匀地间隔开的。
Answer 1:
最后! 随访的线索sdcvvc的回答 ,我们有它:在为O(n log n)的算法的问题! 这也很简单,你了解后。 这些谁猜FFT是正确的。
问题:我们给出一个二进制字符串S
长度为n的,我们要找到三个均匀间隔1秒在里面。 例如, S
可以是110110010
,其中n = 9。 它在位置2,5,和8具有均匀间隔1秒。
扫描S
从左到右,并制作一个列表L
的1.对于位置S=110110010
以上,我们有列表L = [1,2,4,5,8]。 这个步骤是O(n)。 现在的问题是要找到在长度为3的算术级数 L
,即找到一个不同的,B,C在L
使得BA = CB,或者等效A + C = 2b中 。 对于上面的示例,我们想找到的进展(2,5,8)。
使多项式 p
与术语×K个用于每个k L
。 对于上面的例子中,我们使多项式P(X)=(X + X 2 + X 4 + X 5 + X 8)。 这个步骤是O(n)。
找到多项式q
= P 2,使用快速傅立叶变换 。 对于上面的示例,我们得到多项式Q(X)= X 16 + 2×13 + 2×12 + 3×10 + 4×9 + X 8 + 2×7 + 4×6 + 2×5 + X 4 + 2X 3 + X 2。 这个步骤是O(n log n)的。
忽略除了那些对应于x 2K为在某个k的所有术语L
。 对于上面的示例,我们得到的项x 16,3×10,×8,×4,×2。 这一步是O(n),如果你选择做它。
这里的关键点:对于b在任何X 2b的系数L
恰恰是对数(A,C)在L
使得A + C = 2b中 。 [CLRS,例 30.1-7]一种这样的对是(B,B)总是(所以系数至少为1),但如果存在任何其他对(A,C),则系数至少为3,从(A,C )和(C,A)。 对于上面的例子中,我们有×10的系数为3,因为AP(2,5,8)的精确。 (这些系数X 2b中永远是奇数,对于上面的原因,而且在Q所有其他系数将始终是偶数。)
那么,该算法是看这些条款X 2b的系数,看看其中是否大于1,如果没有,那么有没有均匀间隔1秒。 如果在 A B L
为其中x 2b的系数大于1,则我们知道有一些对(A,C) -以外的(B,B) -其为A + C = 2b中 。 找到实际的对中,我们简单地尝试在每一个 L
(相应的C将是图2b-a)和查看是否有一个1在位置2B-一个在S
。 这个步骤是O(n)。
这一切,乡亲。
有人可能会问:我们需要使用FFT? 很多答案,如测试的 , flybywire的 ,和RSP的 ,建议,检查每对1S的,并认为如果有一个1在“第三”的位置,该方法可能为O工作(N log n)的基础上,直觉如果有太多的1S,我们会很容易地找到一个三重的,如果太少1S,检查所有对需要一点时间。 不幸的是,虽然这种直觉是正确的,简单的方法是为O更好(N 2),它是不是好显著。 正如sdcvvc的回答 ,我们可以把长度n = 3 K,以1s的字符串的“坎托状集”在其三元表示具有仅在它的0和2秒(无1S)的位置。 这样的字符串有2 K = N(日志2)/(对数3)≈ñ0.63那些在它和没有均匀间隔1秒,所以检查所有对将是在它的1的数目的平方的数量级:这是的4k≈ñ1.26不幸是渐近比(N log n)的大得多。 事实上,最坏的情况下甚至更糟:利奥Moser的于1953年构造 (有效地)这样的字符串,其具有在其中N 1-C /√(log n)的 1秒,但没有均匀间隔1秒,这意味着,在这样的字符串,则简单方法将采取Θ(N 2-2C /√(log n)的 ) -只有一点点比Θ更好(N 2),令人惊讶!
大约1秒的在长度为n,没有3对均匀隔开的那些的一个字符串(我们在上面看到的是至少n从容易坎托状结构0.63,最大数量至少n 1-C /√(log n)的与莫泽的建设) -这是OEIS A003002 。 它也可以直接从计算OEIS A065825作为K,使得A065825(K)≤Ñ<A065825(K + 1)。 我写了一个程序来找到这些,而且事实证明,贪婪算法不给上最长的字符串。 例如,对于n = 9,我们可以得到5个1S(110100011),但只有贪婪得到4-(110110000),对于n = 26,我们可以得到11个1S(11001010001000010110001101),但贪婪仅给出了8(11011000011011000000000000),以及用于N = 74,我们可以得到22个1S(11000010110001000001011010001000000000000000010001011010000010001101000011),但贪婪使只有16(11011000011011000000000000011011000011011000000000000000000000000000000000)。 他们在相当多的地方一致,除非50(例如,所有的38至50),虽然。 由于OEIS引用说,似乎雅罗斯瓦夫莱夫斯基很关心这个问题,他认为在这些网站的非平均集 。 具体的数字是只知道高达194。
Answer 2:
你的问题就是所谓的AVERAGE 本文 (1999年):
一个问题是3SUM硬如果存在来自问题3SUM一个子二次还原:给定n个整数的组A,在那里元件A,B,C在A使得A + B + C = 0? 它不知道平均值是否是3SUM硬。 但是,从平均3SUM,其说明我们忽略一个简单的线性时间的减少。
维基百科 :
当整数是在范围[-u ... U],3SUM可以以时间为O(n + U LG U)由代表S作为位向量,并使用FFT执行卷积解决。
这足以解决你的问题:)。
什么是非常重要的是,为O(n log n)的是在零和一的数量方面的复杂性,而不是那些的计数(可以给出一个数组,如[1,5,9,15])。 如果检查了一组具有一个等差级数,1点的数量而言,是硬的,并根据该文件在1999年的不更快的算法比为O(n 2)是已知的,并且推测,它不存在。 谁不考虑到这一点每个人都在试图解决一个公开问题。
其他有趣的信息,大多irrevelant:
下界:
一个简单的下界坎托状集(数字1..3 ^ N-1不是在它们的三元膨胀含有1) - 其密度为n ^(log_3 2)(大约0.631)。 因此,任何检查,如果设定不是太大,然后检查所有对是不够的,获得为O(n log n)的。 你必须调查序列聪明。 一个更好的下界是引用在这里 -这是N + 1-C /(的log(n))^(1/2)。 这意味着,Cantor集是不是最佳的。
上界 - 我的旧的算法:
已知的是,对于大的n,的一个子集{1,2,...,N}不含有算术级数具有至多n /(log n)的^(1/20)的元件。 纸张在算术级数三元证明更多:所述集不能包含多于N * 2 28 *(loglogN个/ log n)的1/2的元件。 所以,你可以检查一下,必然实现,如果没有,天真地检查对。 这是O(n 2 * loglogN个/ log n)的算法,为O更快(N 2)。 不幸的是“在三元......”是施普林格-但在第一页是可用的,和本·格林的论述,请点击这里 ,28页,24定理。
顺便说,论文是1999年 - 同年正如我所提到的第一个,所以这可能就是第一个没有提到的结果。
Answer 3:
这不是一个解决方案,但思想的一个类似的线什么Olexiy在想
我用与创建者的最大数量的序列玩耍,他们都是挺有意思的,我起身到125位,这里是第3个数字是由试图插入尽可能多的“1”比特尽可能发现:
- 11011000011011000000000000001101100001101100000000000000000000000000000000000000000110110000110110000000000000011011000011011
- 10110100010110100000000000010110100010110100000000000000000000000000000000000000000101101000101101000000000000101101000101101
- 10011001010011001000000000010011001010011001000000000000000000000000000000000000010011001010011001000000000010011001010011001
请注意,他们是(给定约束条件不是太奇怪),所有分形 。 可能有东西在向后想,也许如果字符串不是一个特性的分形 ,那么它必须有一个重复的模式?
由于测试为更好的词来形容这些数字。
更新:唉它看起来像图案足够大的初始字符串开始时,如分解:10000000000001:
100000000000011
10000000000001101
100000000000011011
10000000000001101100001
100000000000011011000011
10000000000001101100001101
100000000000011011000011010000000001
100000000000011011000011010000000001001
1000000000000110110000110100000000010011
1000000000000110110000110100000000010011001
10000000000001101100001101000000000100110010000000001
10000000000001101100001101000000000100110010000000001000001
1000000000000110110000110100000000010011001000000000100000100000000000001
10000000000001101100001101000000000100110010000000001000001000000000000011
1000000000000110110000110100000000010011001000000000100000100000000000001101
100000000000011011000011010000000001001100100000000010000010000000000000110100001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001100100000000100100000000000010000000010000100000100100010010000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000110000010000000000000000000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001100100000000100100000000000010000000010000100000100100010010000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000110000010000000000000000000001001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001000000000000000000000100100000000000000000000000000000000000011
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001000000000000000000000100100000000000000000000000000000000000011001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001001
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001001000001
100000000000011011000011010000000001001100100000000010000010000000000000110100001001000001000000110001000000001000000000000000000000000000000000000000010000001000000000000001100000000110010000000010010000000000001000000001000010000010010001001000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000011000001000000000000000000000100100000000000000000000000000000000000011001000000000000000000000010010000010000001
1000000000000110110000110100000000010011001000000000100000100000000000001101000010010000010000001100010000000010000000000000000000000000000000000000000100000010000000000000011000000001100100000000100100000000000010000000010000100000100100010010000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000110000010000000000000000000001001000000000000000000000000000000000000110010000000000000000000000100100000100000011
10000000000001101100001101000000000100110010000000001000001000000000000011010000100100000100000011000100000000100000000000000000000000000000000000000001000000100000000000000110000000011001000000001001000000000000100000000100001000001001000100100000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001100000100000000000000000000010010000000000000000000000000000000000001100100000000000000000000001001000001000000110000000000001
Answer 4:
我怀疑,一个简单的办法,看起来像为O(n ^ 2)实际上会产生更好的东西,比如为O(n LN(N))。 称取最长测试(对于任何给定的n)的序列是不包含三个一组的那些,并且把1层的,可以是该序列中的数量的严格限制。
我已经想出一些挥手争论,但我一直没能找到一个整洁的证明。 我会采取刺伤在黑暗中:答案是一个非常聪明的想法,教授也有很长时间了,它来似乎很明显知道,但它太硬的学生。 (如果不是这样,你通过它覆盖的演讲睡着了。)
Answer 5:
修订:2009-10-17 23:00
我已经在大量运行这个(如20万元的字符串),我现在相信这个算法是不是为O(n LOGN)。 尽管如此,它是一个很酷的足够的实施和包含了一些优化,使得它运行的非常快的。 它评估二进制字符串24个或更少位数的所有安排下25秒。
我已经更新了代码以包括0 <= L < M < U <= X-1
从今天早些时候观察。
原版的
这一点,在概念,类似于另外一个问题我回答 。 这种代码也看着三个值中的一个系列,并确定如果三重满足的条件。 这是改编自认为C#代码:
using System;
using System.Collections.Generic;
namespace StackOverflow1560523
{
class Program
{
public struct Pair<T>
{
public T Low, High;
}
static bool FindCandidate(int candidate,
List<int> arr,
List<int> pool,
Pair<int> pair,
ref int iterations)
{
int lower = pair.Low, upper = pair.High;
while ((lower >= 0) && (upper < pool.Count))
{
int lowRange = candidate - arr[pool[lower]];
int highRange = arr[pool[upper]] - candidate;
iterations++;
if (lowRange < highRange)
lower -= 1;
else if (lowRange > highRange)
upper += 1;
else
return true;
}
return false;
}
static List<int> BuildOnesArray(string s)
{
List<int> arr = new List<int>();
for (int i = 0; i < s.Length; i++)
if (s[i] == '1')
arr.Add(i);
return arr;
}
static void BuildIndexes(List<int> arr,
ref List<int> even, ref List<int> odd,
ref List<Pair<int>> evenIndex, ref List<Pair<int>> oddIndex)
{
for (int i = 0; i < arr.Count; i++)
{
bool isEven = (arr[i] & 1) == 0;
if (isEven)
{
evenIndex.Add(new Pair<int> {Low=even.Count-1, High=even.Count+1});
oddIndex.Add(new Pair<int> {Low=odd.Count-1, High=odd.Count});
even.Add(i);
}
else
{
oddIndex.Add(new Pair<int> {Low=odd.Count-1, High=odd.Count+1});
evenIndex.Add(new Pair<int> {Low=even.Count-1, High=even.Count});
odd.Add(i);
}
}
}
static int FindSpacedOnes(string s)
{
// List of indexes of 1s in the string
List<int> arr = BuildOnesArray(s);
//if (s.Length < 3)
// return 0;
// List of indexes to odd indexes in arr
List<int> odd = new List<int>(), even = new List<int>();
// evenIndex has indexes into arr to bracket even numbers
// oddIndex has indexes into arr to bracket odd numbers
List<Pair<int>> evenIndex = new List<Pair<int>>(),
oddIndex = new List<Pair<int>>();
BuildIndexes(arr,
ref even, ref odd,
ref evenIndex, ref oddIndex);
int iterations = 0;
for (int i = 1; i < arr.Count-1; i++)
{
int target = arr[i];
bool found = FindCandidate(target, arr, odd, oddIndex[i], ref iterations) ||
FindCandidate(target, arr, even, evenIndex[i], ref iterations);
if (found)
return iterations;
}
return iterations;
}
static IEnumerable<string> PowerSet(int n)
{
for (long i = (1L << (n-1)); i < (1L << n); i++)
{
yield return Convert.ToString(i, 2).PadLeft(n, '0');
}
}
static void Main(string[] args)
{
for (int i = 5; i < 64; i++)
{
int c = 0;
string hardest_string = "";
foreach (string s in PowerSet(i))
{
int cost = find_spaced_ones(s);
if (cost > c)
{
hardest_string = s;
c = cost;
Console.Write("{0} {1} {2}\r", i, c, hardest_string);
}
}
Console.WriteLine("{0} {1} {2}", i, c, hardest_string);
}
}
}
}
主要区别是:
- 穷举搜索解决方案
此代码生成一个功率设定数据的查找来解决这个算法最难输入。 - 所有的解决方案与最难解决
对于前一个问题的代码生成使用蟒蛇发电机所有的解决方案。 此代码只是显示最难每个模式长度。 - 评分算法
此代码检查从中间元件到其左和右边缘的距离。 的Python代码测试的总和是否高于或低于0。 - 融合在候选
当前的代码从中间向工作边寻找候选人。 在前面的问题的代码向中部边缘的工作。 这最后的变化给出了一个大的性能提升。 - 奇数和偶数池使用
根据在这写结束的观察,代码搜索对对奇数的偶数找到L和U,保持米固定式。 这通过预先计算的信息减少搜索次数。 因此,该代码使用FindCandidate的主循环间接的两个级别,需要两次调用FindCandidate每个中间元素:为偶数,一次是奇数者一次。
总的想法是对的索引,而不是数据的原始表示工作。 计算阵列,其中的出现1允许算法在时间正比于1层的中的数据的数目,而不是在时间成正比的数据的长度延伸。 这是一个标准的转换:创建一个数据结构,使运行速度更快,同时保持相当的问题。
结果已经过时了:删除。
编辑:2009-10-16 18:48
在YX的数据,这是考虑在为代表的硬数据来计算对其他答复一些可信,我得到这些结果...我删除了这些。 他们是过时的。
我想指出,这个数据是不是最难的我的算法,所以我觉得假设YX的分形是解决最困难的是错误的。 对于特定的算法最坏的情况下,我希望,将取决于算法本身并不会可能是在不同的算法是一致的。
编辑:2009-10-17 13:30
在此进一步观察。
首先,转换的0和1的串入索引为1的的各位置的阵列。 都说阵列A的长度是X.那么目标是找到
0 <= L < M < U <= X-1
这样
A[M] - A[L] = A[U] - A[M]
要么
2*A[M] = A[L] + A[U]
由于A [L]和A [U]和为偶数,它们不能(偶数,奇数)或(奇数,偶数)。 对于比赛的搜索可以通过拆分来提高A []为奇数和偶数池和搜索依次以奇数和偶数候选人池对A [M]匹配。
但是,这更多的是比算法的改进性能的优化,我觉得。 比较的数量应该下降,但该算法的顺序应该是相同的。
编辑2009-10-18 00:45
另一种优化发生在我,在同样的考生分成奇数和偶数。 由于三个指标必须添加到3的倍数(A,A + X,A + 2× - 模3是0时,不管A和X),可以L,M,和U分离成它们的模3的值:
M L U
0 0 0
1 2
2 1
1 0 2
1 1
2 0
2 0 1
1 0
2 2
事实上,你可以用奇/偶观察结合这一点,他们分成了国防部6个值:
M L U
0 0 0
1 5
2 4
3 3
4 2
5 1
等等。 这将提供进一步的性能优化而不是一个算法加速。
Answer 6:
没能拿出解决方案尚未:(,但有一些想法。
如果我们从一个相反的问题开始什么:构建以1s的最大数量,并没有任何间隔均匀三重奏的序列。 如果你能证明1S的最大数量为O(N),那么你可以通过仅只有1秒的列表迭代改善你的估计。
Answer 7:
这可能有助于....
这个问题简化为如下:
给定的正整数的序列,发现划分成前缀和后缀这样的连续子序列,该子序列的前缀的总和等于所述子序列的后缀的总和。
例如,给定的序列[ 3, 5, 1, 3, 6, 5, 2, 2, 3, 5, 6, 4 ]
我们会发现的亚序列[ 3, 6, 5, 2, 2]
用的前缀[ 3, 6 ]
用的前缀和9
和后缀[ 5, 2, 2 ]
用的后缀总和9
。
的减少是如下:
由于零和一的序列,并开始在最左边的一个,继续向右移动。 遇到另一个每次,记录的移动次数,因为遇到了前一个,这个数字追加到产生的序列。
例如,给定的序列[ 0, 1, 1, 0, 0, 1, 0, 0, 0, 1 0 ]
我们会发现的减少[ 1, 3, 4]
从该还原,我们计算的连续子序列[ 1, 3, 4]
所述的前缀[ 1, 3]
用的总和4
,和后缀[ 4 ]
用的总和4
。
这种降低可以以被计算O(n)
不幸的是,我不知道在哪里可以从这里走。
Answer 8:
对于简单的问题类型(即您搜索三“1”,只有(即零个或多个)“0”这之间),它很简单:你可以只拆分序列中的每一个“1”,寻找有两个相邻的子序列相同的长度(并非该第二子序列的最后一个,当然)。 显然,这可以在O(n)的时间来完成。
对于更复杂的版本(即您搜索的索引i和一个间隙g> 0,使得s[i]==s[i+g]==s[i+2*g]=="1"
也不太清楚,如果存在的O(N log n)的溶液中,由于有可能具有这种性质的O(N²)三元组(认为全部为一字符串的,大约有N²/ 2这样的三元组)。 当然,你正在寻找只有其中一个,但我现在不知道,怎么找呢?
Answer 9:
一个有趣的问题,但一旦你意识到两个“1'之间的实际模式并不重要,算法变为:
- 扫描寻找一个“1”
- 从另一个“1”的下一个位置开始扫描(到所述阵列的所述端减去从距离当前的第一“1”,否则,第三“1”将是出界)
- 如果在第二个“1”加上距离与第一1' 第三‘1’出现的位置,我们有均匀的空间的。
在代码中,JTEST时尚,(注意此代码不写是最有效的,我加了一些的println的,看看会发生什么。)
import java.util.Random;
import junit.framework.TestCase;
public class AlgorithmTest extends TestCase {
/**
* Constructor for GetNumberTest.
*
* @param name The test's name.
*/
public AlgorithmTest(String name) {
super(name);
}
/**
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
}
/**
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}
/**
* Tests the algorithm.
*/
public void testEvenlySpacedOnes() {
assertFalse(isEvenlySpaced(1));
assertFalse(isEvenlySpaced(0x058003));
assertTrue(isEvenlySpaced(0x07001));
assertTrue(isEvenlySpaced(0x01007));
assertTrue(isEvenlySpaced(0x101010));
// some fun tests
Random random = new Random();
isEvenlySpaced(random.nextLong());
isEvenlySpaced(random.nextLong());
isEvenlySpaced(random.nextLong());
}
/**
* @param testBits
*/
private boolean isEvenlySpaced(long testBits) {
String testString = Long.toBinaryString(testBits);
char[] ones = testString.toCharArray();
final char ONE = '1';
for (int n = 0; n < ones.length - 1; n++) {
if (ONE == ones[n]) {
for (int m = n + 1; m < ones.length - m + n; m++) {
if (ONE == ones[m] && ONE == ones[m + m - n]) {
System.out.println(" IS evenly spaced: " + testBits + '=' + testString);
System.out.println(" at: " + n + ", " + m + ", " + (m + m - n));
return true;
}
}
}
}
System.out.println("NOT evenly spaced: " + testBits + '=' + testString);
return false;
}
}
Answer 10:
我想分而治之的方法,可能的工作。
首先,在预处理需要不到一半的输入大小 / 3)将所有数字到列表中。
给定一个字符串: 0000010101000100
(注意,这个特殊的例子是有效的)
插入所有素数(和1)从1到(16/2)到一个列表:{1,2,3,4,5,6,7}
然后分成两半:
100000101 01000100
坚持做下去,直到你得到尺寸1.字符串对于在他们1全尺寸-一个字符串,添加字符串的可能性列表的索引; 否则,返回-1失败。
您还需要返回仍然可能间隔距离的列表,每个起始索引相关。 (和你一起创业以上的上榜和你去删除号码)这里,一个空列表意味着你只处理一个1等任何间距可能在这一点; 否则该列表包括必须排除间距。
因此,与上面的例子继续:
1000 0101 0100 0100
10 00 01 01 01 00 01 00
1 0 0 0 0 1 0 1 0 1 0 0 0 1 0 0
在第一结合步骤中,我们有八组两个现在。 在第一个,我们有一组的可能性,但我们了解到,间距1是因为其它的零在那里不可能的。 因此,我们返回0(对于指数)和{2,3,4,5,7}的事实,通过间隔1是不可能的。 在第二,我们什么都没有,因此返回-1。 第三,我们有没有在指数5淘汰间距匹配,所以返回5,{1,2,3,4,5,7}。 在第四对我们回到7,{1,2,3,4,5,7}。 在第五,返回图9,{1,2,3,4,5,7}。 在第六,返回-1。 在第七,返回13,{1,2,3,4,5,7}。 在第八,返回-1。
再结合为四组,四个,我们有:
1000
:返回(0,{4,5,6,7}) 0101
:返回(5,{2,3,4,5,6,7}),(7,{1,2,3,4,5 ,6,7}) 0100
:返回(9,{3,4,5,6,7}) 0100
:返回(13,{3,4,5,6,7})
结合成组的八:
10000101
:返回(0,{5,7}),(5,{2,3,4,5,6,7}),(7,{1,2,3,4,5,6,7}) 01000100
:返回(9,{4,7}),(13,{3,4,5,6,7})
组合成一个组16个:
10000101 01000100
正如我们已经进步了,我们继续检查一切准备为止。 截至到这一步,我们已经离开的东西,超出了字符串的结尾,但现在我们可以做好一切准备。
基本上,我们有5至7间距检查第1,发现他们不排队1的。 (请注意,每个检查是恒定的,不是线性的时间)然后我们检查第二个(索引5)6第2间距,3,4,5,,和7--或我们会,但由于我们可以在2停实际上相匹配。
唷! 这是一个相当长的算法。
我不知道100%,如果是因为最后一步的 ,但一切都交给肯定是 ,据我可以告诉。 我会回来稍后,并尝试提炼的最后一步。
编辑:改变了我的答案,以反映Welbog的评论。 很抱歉的错误。 以后我会写一些伪也一样,当我得到多一点的时间来破译我又写了一封信。 ;-)
Answer 11:
我在这里给我的粗略估计,并让那些谁与计算的复杂性是更好地帮助我如何我的算法票价O型符号明智
- 给定二进制串0000010101000100(如实施例)
- 作物头和零点的尾 - > 00000 101010001 00
- 我们得到101010001从前面的计算
- 检查,如果中间比特是“一”,如果属实,发现有效的三个均匀间隔开的“1”(仅当位的数目是奇数)
- 相关地,如果比特的保持裁剪数偶数,头部和尾部“一个”不能是均匀间隔的“一”的一部分,
- 我们使用1010100001为例(使用一个额外的“零”,成为偶数作物),在这种情况下,我们需要重新裁剪,然后变成 - > 10101 00001
- 我们从前面的计算得到10101,检查中间位,我们再次发现均匀间隔位
我不知道如何计算的复杂性这一点,任何人都可以帮忙吗?
编辑:添加一些代码来说明我的想法
EDIT2:试图编译我的代码,并发现了一些重大失误,固定
char *binaryStr = "0000010101000100";
int main() {
int head, tail, pos;
head = 0;
tail = strlen(binaryStr)-1;
if( (pos = find3even(head, tail)) >=0 )
printf("found it at position %d\n", pos);
return 0;
}
int find3even(int head, int tail) {
int pos = 0;
if(head >= tail) return -1;
while(binaryStr[head] == '0')
if(head<tail) head++;
while(binaryStr[tail] == '0')
if(head<tail) tail--;
if(head >= tail) return -1;
if( (tail-head)%2 == 0 && //true if odd numbered
(binaryStr[head + (tail-head)/2] == '1') ) {
return head;
}else {
if( (pos = find3even(head, tail-1)) >=0 )
return pos;
if( (pos = find3even(head+1, tail)) >=0 )
return pos;
}
return -1;
}
Answer 12:
我想出了这样的事情:
def IsSymetric(number):
number = number.strip('0')
if len(number) < 3:
return False
if len(number) % 2 == 0:
return IsSymetric(number[1:]) or IsSymetric(number[0:len(number)-2])
else:
if number[len(number)//2] == '1':
return True
return IsSymetric(number[:(len(number)//2)]) or IsSymetric(number[len(number)//2+1:])
return False
这是由andycjw启发。
- 截断零。
- 如果连然后测试两个子0 - (LEN-2)(跳过最后一个字符)和1 - (LEN-1)(跳过第一个字符)
- 如果没有甚至比如果中间char是一个比我们的成功。 否则划分在midle字符串没有midle元素,并检查两部分。
至于复杂性,这可能是O(nlogn)在我们两个把每个递归。
希望能帮助到你。
Answer 13:
好吧,我会采取另一种刺的问题。 我想我可以证明一个O(N日志(n))的算法,该算法类似于已经使用二叉树来存储1的之间的距离所讨论的那些。 这种方法是由司法部关于减少问题到1的之间的距离的观察名单启发。
我们可以扫描输入字符串以构建周围的位置的平衡二叉树1的,使得每个节点存储1的每个边缘的位置和标记有与相邻的1的距离为每个子节点。 例如:
10010001 gives the following tree
3
/ \
2 / \ 3
/ \
0 7
这可以在O完成(正的log(n)),因为,对于尺寸为n的串,每个插入发生在最坏的情况下为O(log(N))。
那么问题是搜索树去发现是否在任何节点上,有来自通过左子具有相同的距离通过右子路径,该路径节点的路径。 这可以递归每个子树来完成。 当在搜索合并两个子树,我们必须从以正确的路径距离左子树比较来自路径的距离。 由于在子树路径的数量将是成正比的log(n),和节点的数量为n,我相信这可以在O完成(正数(n))的时间。
我错过了什么?
Answer 14:
这所以我决定试试我这似乎喜欢上了一个有趣的问题。
我想提出的假设是111000001将查找第3分者,并获得成功。 基本按照1个零的数量是重要的,因为0111000是按照自己的定义一样的111000。 一旦你找到的1两种情况,在未来1个中发现完成了三部曲。
这是在Python:
def find_three(bstring):
print bstring
dict = {}
lastone = -1
zerocount = 0
for i in range(len(bstring)):
if bstring[i] == '1':
print i, ': 1'
if lastone != -1:
if(zerocount in dict):
dict[zerocount].append(lastone)
if len(dict[zerocount]) == 2:
dict[zerocount].append(i)
return True, dict
else:
dict[zerocount] = [lastone]
lastone = i
zerocount = 0
else:
zerocount = zerocount + 1
#this is really just book keeping, as we have failed at this point
if lastone != -1:
if(zerocount in dict):
dict[zerocount].append(lastone)
else:
dict[zerocount] = [lastone]
return False, dict
这是第一次尝试,所以我敢肯定,这可以在一个更清洁的方式来写。 请列出其中这些方法如下失败下来的情况。
Answer 15:
我想这是n日志(n)是由于以下原因:
- 为了找到1是三重的开始,你需要检查(N-2)字符。 如果你还没有到那个时候发现了它,你不会(字符n-1和n不能启动三重)(O(N))
- 到找到第二个1是三重态(由第一个启动)的一部分,则需要检查M / 2(M = NX,其中X是所述第一1的偏移量)的字符。 这是因为,如果你还没有被你从第一个到最后一半是时发现的第二个1,你不会......,因为第三个1必须完全过去的第二相同的距离。 (O(的log(n)))
- 它O(1)找到最后1,因为你知道它必须通过的时间是在索引找到第一个和第二个。
所以,你有N,日志(n)和1 ... O(nlogn)
编辑:哎呀,我的坏。 我的大脑有它设置N / 2 LOGN ......它显然不是(上翻一番项目的数量还是双打迭代的内部循环数)。 这仍然是在N ^ 2,而不是解决问题。 好吧,至少我写一些代码:)
实施的Tcl
proc get-triplet {input} {
for {set first 0} {$first < [string length $input]-2} {incr first} {
if {[string index $input $first] != 1} {
continue
}
set start [expr {$first + 1}]
set end [expr {1+ $first + (([string length $input] - $first) /2)}]
for {set second $start} {$second < $end} {incr second} {
if {[string index $input $second] != 1} {
continue
}
set last [expr {($second - $first) + $second}]
if {[string index $input $last] == 1} {
return [list $first $second $last]
}
}
}
return {}
}
get-triplet 10101 ;# 0 2 4
get-triplet 10111 ;# 0 2 4
get-triplet 11100000 ;# 0 1 2
get-triplet 0100100100 ;# 1 4 7
Answer 16:
我想我已经找到了解决问题的办法,但我不能建立一个正式的证明。 我提出的解决方案是用Java编写的,它使用反“N”来算多少列表/数组访问它。 因此n应小于或等于stringLength *日志(stringLength),如果它是正确的。 我试了数字0到2 ^ 22,和它的作品。
它首先遍历输入字符串,使所有这些都持有一个索引列表。 这仅仅是为O(n)。
然后从索引列表它挑选一个firstIndex和和secondIndex比第一较大。 这两个指标必须持有的,因为它们在索引列表。 从那里thirdIndex可以计算出来。 如果inputString [thirdIndex]是一个1,则它停止。
public static int testString(String input){
//n is the number of array/list accesses in the algorithm
int n=0;
//Put the indices of all the ones into a list, O(n)
ArrayList<Integer> ones = new ArrayList<Integer>();
for(int i=0;i<input.length();i++){
if(input.charAt(i)=='1'){
ones.add(i);
}
}
//If less than three ones in list, just stop
if(ones.size()<3){
return n;
}
int firstIndex, secondIndex, thirdIndex;
for(int x=0;x<ones.size()-2;x++){
n++;
firstIndex = ones.get(x);
for(int y=x+1; y<ones.size()-1; y++){
n++;
secondIndex = ones.get(y);
thirdIndex = secondIndex*2 - firstIndex;
if(thirdIndex >= input.length()){
break;
}
n++;
if(input.charAt(thirdIndex) == '1'){
//This case is satisfied if it has found three evenly spaced ones
//System.out.println("This one => " + input);
return n;
}
}
}
return n;
}
附加说明:当它遍历输入字符串来构建索引列表计数器n不会增加。 这种操作是O(n),所以它不会对算法复杂度的效果呢。
Answer 17:
一个迈进了问题是要考虑的因素和转移。
随着移动,你比较1和0与自身的位移版本的字符串。 然后你把匹配的。 就拿这个例子中两个转变:
1010101010
1010101010
------------
001010101000
将得到的1的(逐位AND运算),必须代表其被均匀地由两个隔开所有那些1的。 相同的示例偏移为三个:
1010101010
1010101010
-------------
0000000000000
在这种情况下有其均匀地间隔开的三个开1号的。
那么,这告诉你吗? 好了,你只需要测试这是质数的变化。 例如说,你有两个1的这六个分开。 你只需要测试“两化”的变化和“三化”的变化(因为这些划分为六个)。 例如:
10000010
10000010 (Shift by two)
10000010
10000010 (We have a match)
10000010
10000010 (Shift by three)
10000010 (We have a match)
所以,你需要检查的唯一的变化是2,3,5,7,11,13等多达素最接近的数字串的大小的平方根。
几乎解决了吗?
我觉得我更接近的解决方案。 基本上:
- 扫描1的字符串。 对于每1注是利用其位置的模后的余数。 模量的范围从1到所述串的大小的一半。 这是因为最大可能的分离尺寸为一半的字符串。 这是在为O(n ^ 2)来完成。 但。 只有总理模量需要进行检查,以便为O(n ^ 2 /的log(n))
- 排序为了最大模数模/余数榜第一,这可以在O完成(N *的log(n))的时间。
- 寻找三个连续模/余哪都一样。
- 不知怎的,检索者的位置!
我认为最大的线索答案,是最快的排序算法,为O(N *的log(n))。
错误
作为一个同事指出,第1步是错误的。 如果我们有1层的在2,12位和102然后以10模数,他们都会有相同的余数,可是不等距间隔! 抱歉。
Answer 18:
这里有一些想法,尽管我尽了最大努力,将似乎没有将自己包裹起来的蝴蝶结。 尽管如此,他们可能是某人的分析非常有用的起点。
考虑提出的解决方案如下,这是一些人所建议的,包括我自己在这个答案的先前版本的方法。 :)
- 修剪开头和结尾零。
- 扫描寻找1的字符串。
- 当1被发现:
- 假设它是解决方案的中间件1。
- 对于每一个先前1,使用它的保存位置来计算最终1的预期位置。
- 如果计算出的位置是字符串结束后也不能成为解决方案的一部分,所以从候选人名单下降的位置。
- 检查解决方案。
- 如果没有找到解决办法,目前加1,候选人名单。
- 重复,直到没有更多1点的发现。
现在考虑输入字符串串像下面,不会有一个解决方案:
101
101001
1010010001
101001000100001
101001000100001000001
在一般情况下,这是在表格J 0的后跟一个1对于j从零到K-1的k个字符串的连接。
k=2 101
k=3 101001
k=4 1010010001
k=5 101001000100001
k=6 101001000100001000001
需要注意的是子串的长度是1,2,3,等,所以,问题大小n具有长度1的子串到k使得n = K(K + 1)/ 2。
k=2 n= 3 101
k=3 n= 6 101001
k=4 n=10 1010010001
k=5 n=15 101001000100001
k=6 n=21 101001000100001000001
式中,k还跟踪1点是我们必须要考虑的数目。 请记住,每一次我们看到一个1,我们需要考虑所有的1,迄今为止看到的。 所以,当我们看到第二个1,我们只考虑第一,当我们看到第三个1,我们重新考虑了前两个,当我们看到第四个1,我们需要重新考虑的前三个,等等。 由算法结束时,我们考虑K(K-1)/ 2线对1的的。 调用页。
k=2 n= 3 p= 1 101
k=3 n= 6 p= 3 101001
k=4 n=10 p= 6 1010010001
k=5 n=15 p=10 101001000100001
k=6 n=21 p=15 101001000100001000001
n和p之间的关系是N = P + K。
通过串去的过程需要O(n)的时间。 遇到1每一次,最多(K-1)的比较完成的。 由于n = K(K + 1)/ 2,N> K ** 2,所以SQRT(N)>ķ。 这给我们为O(n SQRT(N)),或为O(n ** 3/2)。 但是请注意,可能不是一个真正的紧约束,因为比较的数量从1到最大k的,它不是k的全部时间。 但我不知道如何解释,在数学。
它仍然不是O(N日志(N))。 另外,我也不能证明这些投入是最糟糕的情况下,虽然我怀疑他们。 我想,我对前面结果的更密集在年底甚至稀疏的包装。
由于有人仍可能会发现它很有用,这是我对Perl编写的解决方案代码:
#!/usr/bin/perl
# read input as first argument
my $s = $ARGV[0];
# validate the input
$s =~ /^[01]+$/ or die "invalid input string\n";
# strip leading and trailing 0's
$s =~ s/^0+//;
$s =~ s/0+$//;
# prime the position list with the first '1' at position 0
my @p = (0);
# start at position 1, which is the second character
my $i = 1;
print "the string is $s\n\n";
while ($i < length($s)) {
if (substr($s, $i, 1) eq '1') {
print "found '1' at position $i\n";
my @t = ();
# assuming this is the middle '1', go through the positions
# of all the prior '1's and check whether there's another '1'
# in the correct position after this '1' to make a solution
while (scalar @p) {
# $p is the position of the prior '1'
my $p = shift @p;
# $j is the corresponding position for the following '1'
my $j = 2 * $i - $p;
# if $j is off the end of the string then we don't need to
# check $p anymore
next if ($j >= length($s));
print "checking positions $p, $i, $j\n";
if (substr($s, $j, 1) eq '1') {
print "\nsolution found at positions $p, $i, $j\n";
exit 0;
}
# if $j isn't off the end of the string, keep $p for next time
push @t, $p;
}
@p = @t;
# add this '1' to the list of '1' positions
push @p, $i;
}
$i++;
}
print "\nno solution found\n";
Answer 19:
当扫描1S,增加他们的位置列表。 当添加第二和后续1S,到目前为止,他们比较列表中的每个位置。 间距等于currentOne(中心) - previousOne(左)。 右侧位为currentOne +间距。 如果是1,末尾。
者的名单和他们之间的空间负增长。 简单地说,如果你有很多1之间0的(如在最坏的情况下),你知道1S的名单将相当缓慢增长。
using System;
using System.Collections.Generic;
namespace spacedOnes
{
class Program
{
static int[] _bits = new int[8] {128, 64, 32, 16, 8, 4, 2, 1};
static void Main(string[] args)
{
var bytes = new byte[4];
var r = new Random();
r.NextBytes(bytes);
foreach (var b in bytes) {
Console.Write(getByteString(b));
}
Console.WriteLine();
var bitCount = bytes.Length * 8;
var done = false;
var onePositions = new List<int>();
for (var i = 0; i < bitCount; i++)
{
if (isOne(bytes, i)) {
if (onePositions.Count > 0) {
foreach (var knownOne in onePositions) {
var spacing = i - knownOne;
var k = i + spacing;
if (k < bitCount && isOne(bytes, k)) {
Console.WriteLine("^".PadLeft(knownOne + 1) + "^".PadLeft(spacing) + "^".PadLeft(spacing));
done = true;
break;
}
}
}
if (done) {
break;
}
onePositions.Add(i);
}
}
Console.ReadKey();
}
static String getByteString(byte b) {
var s = new char[8];
for (var i=0; i<s.Length; i++) {
s[i] = ((b & _bits[i]) > 0 ? '1' : '0');
}
return new String(s);
}
static bool isOne(byte[] bytes, int i)
{
var byteIndex = i / 8;
var bitIndex = i % 8;
return (bytes[byteIndex] & _bits[bitIndex]) > 0;
}
}
}
Answer 20:
我想我会发布的第22天真的解决问题的方法前加一个注释。 对于天真的解决方案,我们并不需要证明1名的字符串中的数量最多为O(日志(N)),而是它至多是O(开方(N *的log(n))。
求解:
def solve(Str):
indexes=[]
#O(n) setup
for i in range(len(Str)):
if Str[i]=='1':
indexes.append(i)
#O((number of 1's)^2) processing
for i in range(len(indexes)):
for j in range(i+1, len(indexes)):
indexDiff = indexes[j] - indexes[i]
k=indexes[j] + indexDiff
if k<len(Str) and Str[k]=='1':
return True
return False
它基本上类似于flybywire的思想和实现公平一点,但放眼望去,而不是返回。
贪婪的字符串构建:
#assumes final char hasn't been added, and would be a 1
def lastCharMakesSolvable(Str):
endIndex=len(Str)
j=endIndex-1
while j-(endIndex-j) >= 0:
k=j-(endIndex-j)
if k >= 0 and Str[k]=='1' and Str[j]=='1':
return True
j=j-1
return False
def expandString(StartString=''):
if lastCharMakesSolvable(StartString):
return StartString + '0'
return StartString + '1'
n=1
BaseStr=""
lastCount=0
while n<1000000:
BaseStr=expandString(BaseStr)
count=BaseStr.count('1')
if count != lastCount:
print(len(BaseStr), count)
lastCount=count
n=n+1
(在我的防守,我仍然在了解了“学习Python”阶段)
此外,从字符串的贪婪建设可能有用的输出,还有创下1的数量......我不愿意坐等见证创下2096 2的幂后一个相当一致的跳跃。
strlength # of 1's
1 1
2 2
4 3
5 4
10 5
14 8
28 9
41 16
82 17
122 32
244 33
365 64
730 65
1094 128
2188 129
3281 256
6562 257
9842 512
19684 513
29525 1024
Answer 21:
我会试着提出一个数学方法。 这是一个多结束一个开始,所以任何帮助,评论,甚至是矛盾的 - 将十分赞赏。 然而,如果这种方法被证明 - 算法是串在一条直线向前搜索。
给定一个固定数目的空格k
和串S
,寻找一个k间隔三重花费O(n)
-我们简单地测试每一个0<=i<=(n-2k)
如果S[i]==S[i+k]==S[i+2k]
。 该测试需要O(1)
我们做nk
倍其中k
是一个常数,所以它需要O(nk)=O(n)
。
让我们假设存在的数量之间成反比1
的,我们需要搜索的最大空间。 也就是说,如果有很多1
的,必须有三重,它必须是相当密集; 如果只有少数1
的,三态(如果有的话),可以说是相当的稀疏。 换句话说,我可以证明,如果我有足够的1
的,这样的三重必须存在-而且越1
的我,更密集的三重必须找到。 这可以通过解释鸽巢原理 -希望以后这样来阐述。
假设有一个上限k
上的空间我必须寻找可能的数量。 现在,每个1
位于S[i]
,我们需要检查1
在S[i-1]
和S[i+1]
, S[i-2]
和S[i+2]
,... S[ik]
和S[i+k]
。 这需要O((k^2-k)/2)=O(k^2)
对于每个1
在S
-由于高斯系列求和公式 。 请注意,这不同于第1部分-我有k
为空格数作为上限,而不是作为一个恒定的空间。
我们需要证明O(n*log(n))
也就是说,我们需要证明k*(number of 1's)
成正比log(n)
如果我们能做到这一点,该算法是微不足道的-每个1
的S
,其指数是i
,单纯看为1
的每一方达距离k
。 如果在同样的距离中发现了两个,回到i
和k
。 再次,棘手的部分将是寻找k
和证明的正确性。
我真的很感激您的意见在这里-我一直在试图找到之间的关系k
的数量和1
的对我的白板上,至今没有成功。
Answer 22:
假设:
刚才错了,谈论的log(n)的那些的上限数量
编辑:
现在我发现,使用康托尔数(是否正确),对集密度为(2/3)^ Log_3(N)(这真是个奇怪的功能)和我同意,的log(n)/ N密度是很强的。
如果这是上限,有algorhitm谁在至少Ø解决了这个问题(N *(3/2)^(的log(n)/日志(3)))的时间复杂度和O((3/2)^(的log(n)/日志(3)))的空间复杂度。 (检查法官对algorhitm回答)
这仍是目前为O更好(N ^ 2)
此功能((3/2)^(的log(n)/日志(3)))真的象的n * log(n)的上一见倾心。
我是怎样得到这个公式?
在串Applaying领唱号。
Supose字符串的那长度为3 ^ P ==Ñ
在代康托尔串的每一步你保持者的prevous数的2/3。 应用此P次。
该平均值(n *((2/3)^ P)) - >(((3 ^ P))*((2/3)^ P))剩余的和简化后2 ^ P。 这意味着2 ^ρ个在3 ^ P串 - >(3/2)^ P的。 替代P =的log(n)/日志(3),并得到
((3/2)^(的log(n)/日志(3)))
Answer 23:
怎么样一个简单的O(n)的解决方案,为O(n ^ 2)空间? (使用这样的假设:o所有位运算符的工作(1)。)
算法大致分为四个阶段:
第1阶段:对于你原来的号码的每一位,找出远离那些有多远,但只考虑一个方向。 (I认为是在至少显著位的方向上的所有的位。)
第2阶段:在反向输入处的比特的顺序;
阶段3:重新运行上输入反相步骤1。
第四阶段:从第1阶段和第3阶段进行比较的结果。如果任何位被同样的上方和下方,我们必须有一