【问题标题】:Simple algorithm analysis简单算法分析
【发布时间】:2012-05-24 15:13:25
【问题描述】:

我正在尝试将算法降低到至少 O(n^(3/2)) 复杂度。这是算法:

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;
}

第一个 for 循环将迭代 n/2 次,即 O(n) 复杂度。我需要让内部 for 循环最多为 O(sqrt(n)),从而使整个算法具有 O(n^(3/2)) 复杂度。我很难弄清楚嵌套的 for 循环是否是我需要的正确复杂性。

注意:
n 是字符串的大小。该函数主要检查字符串 s 中是否出现重复模式。 s 中仅有的字符是"0""1"。例如,如果字符串为"001001",则模式为"001" 并出现两次。字符串也是偶数。话虽如此,语法和功能与这个问题无关。所有基本动作都被认为需要 O(1)(常数)时间,这几乎是这段代码的全部内容。

注意 2:
我这样做是为了做作业。但作业问题只是让算法正常工作,我已经做到了。降低复杂性只是额外的练习。

任何帮助或指导将不胜感激!

【问题讨论】:

  • 算法是做什么的?
  • 我在代码下的“注:”中解释了这一点。它确定字符串 s 是否由重复模式组成。例如,“001001”由“001”两次组成。 “000000”由“0”组成6次。 “010100”是不由模式组成的示例。
  • 这是一个 O(N) 的工作。您需要稍微修改的字符串搜索算法。
  • 我的意思是,像 Knuth-Morris-Pratt 这样的 O(N) 字符串搜索算法。
  • @svinja:这称为“查找字符串的句点”。找到一个简单的方法是在其自身的正方形内搜索一个字符串(将第一个和最后一个字符切掉,以消除琐碎的情况)。有一个 article (pdf) 讨论了具有更好平均运行时间的算法。

标签: algorithm complexity-theory analysis


【解决方案1】:

很简单,只需检查长度是否除以总长度(必须,如果L不除总长度,则字符串不能是长度为L的重复模式)并且不要运行如果没有,则内部循环...除数数的上限是 2sqrt(n) 所以这保证了 O(Nsqrt(N))。

如果你想知道为什么,一个数字可以有的最大除数是每个数字直到 sqrt(n),然后对于每个数字 x,N/x。所以在 2sqrt(N) 以下。

当然,数字在现实中的除数要少得多,除了 12 实际上拥有所有除数:1、2、3(每个数字都达到 sqrt)、12/1、12/2、12/3(逆)。

有 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;
    }

关键是:

if (n % l != 0) continue;

否则将是 O(N^2)。

虽然外循环乍一看似乎是 N/2,但从数学上可以保证它小于 2sqrt(N)。您还可以通过在几百万个字符的字符串上运行它来看到它 - 它会很快工作。

【讨论】:

  • 哦,这很有意义。我对我的内部循环有多复杂感到困惑。非常感谢,这澄清了一些事情!
【解决方案2】:

我认为你的内循环不能降低到 O(sqrt(n)),因为你必须将字符串开头的所有字符与特定索引 i 中的字符进行比较,其值由外循环控制。

【讨论】:

  • 它表示整个算法可以在 O(n^3/2) 复杂度内完成。我认为外部循环必须是 O(n),然后是内部 O(sqrt(n)),这就是我设计它的方式。是否应该翻转?
猜你喜欢
  • 2013-09-11
  • 2014-10-19
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
相关资源
最近更新 更多