简体   繁体   English

简单的算法分析

[英]Simple algorithm analysis

I am trying to get an algorithm down to at least O(n^(3/2)) complexity. 我试图将算法降低到至少O(n ^(3/2))的复杂度。 Here is the algorithm: 这是算法:

function( string s, int n )
{
    bool result = false;
    int position = 0;
    for( int i = 0; i < n/2; i++ )
    {
        position = 0;
        for( int j = i+1; j < n; j++ )
        {
            if( s[j] != s[position] ) break;        
            if( j == n ) result = true;
            if( position == i ) position = 0;
            else position++;        
        }
        if(result) break;       
    }
    return result;
}

The first for-loop will iterate n/2 times, which is O(n) complexity. 第一个for循环将迭代n / 2次,这是O(n)复杂度。 I need to get the inside for-loop to be at most O(sqrt(n)), thus giving the entire algorithm a O(n^(3/2)) complexity. 我需要让内部for循环最多为O(sqrt(n)),从而使整个算法具有O(n ^(3/2))复杂度。 I am having difficulty trying to figure out if the nested for loop is the right complexity I need. 我很难弄清楚嵌套for循环是否是我需要的正确复杂性。

Note: 注意:
n is the size of the string. n是字符串的大小。 The function basically checks to see if a repeating pattern occurs in the string s. 该函数基本上检查字符串s中是否出现重复模式。 The only characters in s are "0" and "1" . s中唯一的字符是"0""1" For example, if the string is "001001" , then the pattern is "001" and occurs twice. 例如,如果字符串是"001001" ,则模式为"001"并且发生两次。 The string is also even. 字符串也是均匀的。 That being said, syntax and functionally are irrelevant for this question. 话虽这么说,语法和功能与这个问题无关。 All basic actions are considered to take O(1) (constant) time, which is pretty much the entirety of this code. 所有基本操作都被认为需要O(1)(常量)时间,这几乎就是这段代码的全部内容。

Note2: 笔记2:
I am doing this for homework. 我这样做是为了完成家庭作业。 But the homework question was just to get the algorithm working, which I have done. 但是功课问题只是为了让算法正常工作,我已经完成了。 Getting the complexity down is just extra work to practise. 降低复杂性只是练习的额外工作。

Any help or guidance would be appreciated! 任何帮助或指导将不胜感激!

It is very easy, simply check whether the length divides the total length (it has to, a string can't be a repeating pattern of length L if L doesn't divide the total length) and don't run the inner loop if it doesn't... Upper bound of number of divisors is 2sqrt(n) so this guarantees O(Nsqrt(N)). 这很简单,只需检查长度是否除以总长度(如果L没有除以总长度,则字符串不能是长度为L的重复模式),如果长度除以总长度,则不要运行内部循环它没有...除数的上限是2sqrt(n)所以这保证了O(Nsqrt(N))。

If you're wondering why, the maximum number of divisors a number could have is every number up to sqrt(n), and then for each of those numbers x, N/x. 如果你想知道为什么,一个数字可以有的最大除数是每个数字直到sqrt(n),然后是每个数字x,N / x。 So under 2sqrt(N). 所以在2sqrt(N)之下。

Of course, numbers have a lot less divisors in reality, except for 12 which actually has all of them: 1,2,3 (every number up to sqrt), 12/1, 12/2, 12/3 (inverses). 当然,实际上数字的除数要少得多,除了12实际上它们全部都有:1,2,3(每个数字直到sqrt),12 / 1,2 / 2,12 / 3(反转)。

There are 2 inner loops but one runs L times and the other one N/L times so the inner loops are O(N). 有2个内环,但一个运行L次,另一个运行N / L次,因此内环是O(N)。

    static bool f(string s)
    {
        int n = s.Length;
        for (int l = n / 2; l >= 1; l--)
        {
            if (n % l != 0) continue;
            bool d = true;
            for (int o = 0; o < l; o++)
            {
                char f = s[o];
                for (int p = l; p < n; p += l)
                    if (s[p + o] != f) d = false;
            }
            if (d == true) return true;
        }
        return false;
    }

The key line is: 关键是:

if (n % l != 0) continue;

otherwise it would be O(N^2). 否则它将是O(N ^ 2)。

While the outer loop may seem to be N/2 at first glance, it is mathematically guaranteed to be < 2sqrt(N). 虽然外环看起来似乎是N / 2,但在数学上保证<2sqrt(N)。 Which you can also see by running it on a string of a few million characters - it will work quickly. 您还可以通过在几百万个字符的字符串上运行它来查看 - 它可以快速工作。

我认为你的内部循环不能降低到O(sqrt(n)),因为你必须比较从字符串的开头到特定索引的那些字符,其中的值由外部循环控制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM