I am trying to get an algorithm down to at least O(n^(3/2)) complexity. 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. 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. I am having difficulty trying to figure out if the nested for loop is the right complexity I need.
Note:
n is the size of the string. The function basically checks to see if a repeating pattern occurs in the string s. The only characters in s are "0" and "1". For example, if the string is "001001", then the pattern is "001" and occurs twice. 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.
Note2:
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)).
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. So under 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).
There are 2 inner loops but one runs L times and the other one N/L times so the inner loops are 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).
While the outer loop may seem to be N/2 at first glance, it is mathematically guaranteed to be < 2sqrt(N). Which you can also see by running it on a string of a few million characters - it will work quickly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With