O(nlogn)算法 - 查找二进制字符串中的三个均匀间隔的人(O(nlogn) Algorithm

2019-07-23 03:01发布

昨天我上的算法测试这个问题,我想不出答案。 这是推动我绝对是疯了,因为它是价值约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秒。

  1. 扫描S从左到右,并制作一个列表L的1.对于位置S=110110010以上,我们有列表L = [1,2,4,5,8]。 这个步骤是O(n)。 现在的问题是要找到在长度为3的算术级数 L ,即找到一个不同的,B,CL使得BA = CB,或者等效A + C = 2b中 。 对于上面的示例,我们想找到的进展(2,5,8)。

  2. 使多项式 p与术语×K用于每个k L 。 对于上面的例子中,我们使多项式P(X)=(X + X 2 + X 4 + X 5 + X 8)。 这个步骤是O(n)。

  3. 找到多项式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)的。

  4. 忽略除了那些对应于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);
            }
        }
    }
}

主要区别是:

  1. 穷举搜索解决方案
    此代码生成一个功率设定数据的查找来解决这个算法最难输入。
  2. 所有的解决方案与最难解决
    对于前一个问题的代码生成使用蟒蛇发电机所有的解决方案。 此代码只是显示最难每个模式长度。
  3. 评分算法
    此代码检查从中间元件到其左和右边缘的距离。 的Python代码测试的总和是否高于或低于0。
  4. 融合在候选
    当前的代码从中间向工作边寻找候选人。 在前面的问题的代码向中部边缘的工作。 这最后的变化给出了一个大的性能提升。
  5. 奇数和偶数池使用
    根据在这写结束的观察,代码搜索对对奇数的偶数找到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型符号明智

  1. 给定二进制串0000010101000100(如实施例)
  2. 作物头和零点的尾 - > 00000 101010001 00
  3. 我们得到101010001从前面的计算
  4. 检查,如果中间比特是“一”,如果属实,发现有效的三个均匀间隔开的“1”(仅当位的数目是奇数)
  5. 相关地,如果比特的保持裁剪数偶数,头部和尾部“一个”不能是均匀间隔的“一”的一部分,
  6. 我们使用1010100001为例(使用一个额外的“零”,成为偶数作物),在这种情况下,我们需要重新裁剪,然后变成 - > 10101 00001
  7. 我们从前面的计算得到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启发。

  1. 截断零。
  2. 如果连然后测试两个子0 - (LEN-2)(跳过最后一个字符)和1 - (LEN-1)(跳过第一个字符)
  3. 如果没有甚至比如果中间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注是利用其位置的模后的余数。 模量的范围从1到所述串的大小的一半。 这是因为最大可能的分离尺寸为一半的字符串。 这是在为O(n ^ 2)来完成。 但。 只有总理模量需要进行检查,以便为O(n ^ 2 /的log(n))
  2. 排序为了最大模数模/余数榜第一,这可以在O完成(N *的log(n))的时间。
  3. 寻找三个连续模/余哪都一样。
  4. 不知怎的,检索者的位置!

我认为最大的线索答案,是最快的排序算法,为O(N *的log(n))。

错误

作为一个同事指出,第1步是错误的。 如果我们有1层的在2,12位和102然后以10模数,他们都会有相同的余数,可是不等距间隔! 抱歉。



Answer 18:

这里有一些想法,尽管我尽了最大努力,将似乎没有将自己包裹起来的蝴蝶结。 尽管如此,他们可能是某人的分析非常有用的起点。

考虑提出的解决方案如下,这是一些人所建议的,包括我自己在这个答案的先前版本的方法。 :)

  1. 修剪开头和结尾零。
  2. 扫描寻找1的字符串。
  3. 当1被发现:
    1. 假设它是解决方案的中间件1。
    2. 对于每一个先前1,使用它的保存位置来计算最终1的预期位置。
    3. 如果计算出的位置是字符串结束后也不能成为解决方案的一部分,所以从候选人名单下降的位置。
    4. 检查解决方案。
  4. 如果没有找到解决办法,目前加1,候选人名单。
  5. 重复,直到没有更多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:

我会试着提出一个数学方法。 这是一个多结束一个开始,所以任何帮助,评论,甚至是矛盾的 - 将十分赞赏。 然而,如果这种方法被证明 - 算法是串在一条直线向前搜索。

  1. 给定一个固定数目的空格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)

  2. 让我们假设存在的数量之间成反比1的,我们需要搜索的最大空间。 也就是说,如果有很多1的,必须有三重,它必须是相当密集; 如果只有少数1的,三态(如果有的话),可以说是相当的稀疏。 换句话说,我可以证明,如果我有足够的1的,这样的三重必须存在-而且越1的我,更密集的三重必须找到。 这可以通过解释鸽巢原理 -希望以后这样来阐述。

  3. 假设有一个上限k上的空间我必须寻找可能的数量。 现在,每个1位于S[i] ,我们需要检查1S[i-1]S[i+1]S[i-2]S[i+2] ,... S[ik]S[i+k] 。 这需要O((k^2-k)/2)=O(k^2)对于每个1S -由于高斯系列求和公式 。 请注意,这不同于第1部分-我有k为空格数作为上限,而不是作为一个恒定的空间。

我们需要证明O(n*log(n)) 也就是说,我们需要证明k*(number of 1's)成正比log(n)

如果我们能做到这一点,该算法是微不足道的-每个1S ,其指数是i ,单纯看为1的每一方达距离k 。 如果在同样的距离中发现了两个,回到ik 。 再次,棘手的部分将是寻找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阶段进行比较的结果。如果任何位被同样的上方和下方,我们必须有一