我试图将算法降低到至少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:
我这样做是为了完成家庭作业。但是功课问题只是为了让算法正常工作,我已经完成了。降低复杂性只是练习的额外工作。
任何帮助或指导都将不胜感激!
答案 0 :(得分:2)
这很容易,只需检查长度是否除以总长度(如果L不分割总长度,则必须为,字符串不能是长度为L的重复模式)并且不运行如果没有内循环...除数的上限是2sqrt(n),所以这保证了O(Nsqrt(N))。
如果你想知道为什么,一个数字可以有的最大除数是每个数字直到sqrt(n),然后是每个数字x,N / x。所以在2sqrt(N)之下。
当然,实际上数字的除数要少得多,除了实际上全部有12的除数:1,2,3(每个数字直到sqrt),12 / 1,2 / 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,但在数学上保证<&lt; 2sqrt(N)。你可以通过在几百万个字符的字符串上运行它来看到它 - 它会很快起作用。
答案 1 :(得分:0)
我认为你的内部循环不能降低到O(sqrt(n)),因为你必须比较从字符串的开头到特定索引i的所有字符,其值由外部循环控制。