2016-04-08 10 views
2

Ich versuche, die Zeitkomplexität dieses Algorithmus zu berechnen, der bestimmt, ob eine positive Ganzzahl N als x^y ausgedrückt werden kann. Der Autor des Algorithmus ist Vaibhav Gupta.Berechnen der Zeitkomplexität dieses Algorithmus

// Returns true if n can be written as x^y 
bool isPower(unsigned int n) 
{ 
    // Base case 
    if (n <= 1) return true; 

    // Try all numbers from 2 to sqrt(n) as base 
    for (int x=2; x<=sqrt(n); x++) 
    { 
     unsigned p = x; 

     // Keep multiplying p with x while is smaller 
     // than or equal to x 
     while (p <= n) 
     { 
      p *= x; 
      if (p == n) 
       return true; 
     } 
    } 
    return false; 
} 

Der Autor sagt, dass dieser Algorithmus ist eine optimierte Version des ersten, das ist:

// Returns true if n can be written as x^y 
bool isPower(unsigned n) 
{ 
    if (n==1) return true; 

    // Try all numbers from 2 to sqrt(n) as base 
    for (int x=2; x<=sqrt(n); x++) 
    { 
     unsigned y = 2; 
     unsigned p = pow(x, y); 

     // Keep increasing y while power 'p' is smaller 
     // than n. 
     while (p<=n && p>0) 
     { 
      if (p==n) 
       return true; 
      y++; 
      p = pow(x, y); 
     } 
    } 
    return false; 
} 

Ist diese erste eine andere Zeitkomplexität hat, seit er die pow-Funktion verwendet?

+0

Für mich ist das sehr seltsam, dass es keine Prüfung 'if (n% x! = 0) fortfahren;' direkt vor 'while'. Gibt es einen Grund, diese Optimierung zu vermeiden? – Ilya

+0

@ilya - Die Frage ist nicht darüber. Es geht um die Komplexität des Algorithmus * wie beschrieben *. –

Antwort

1

mir Sieht aus wie die äußere Schleife Quadratwurzel von n ist und die inneren Schleifen sind in der Größenordnung von log n (da die Zahl wächst exponentiell) so Ihre Komplexität sollte etwas in der Größenordnung von

O(sqrt(n)*log n) 
sein
+1

Die innere Schleife wird log_x (n) mal ausgeführt (log_x ist log base x). Warum ist es zulässig, die sich ändernde Basis bei der Summierung zu ignorieren? –

+0

@PaulHankin Ja, weil Sie jede Logarithmusbasis A von x in eine Logarithmusbasis b von x umwandeln können, indem Sie einfach mit einer Konstanten multiplizieren, und konstante Multiplikatoren gehen weg mit Groß-O Notation :) – Rob

+0

@PaulHankin Ich beantwortete eine ähnliche Frage eine Weile zurück :) http://stackoverflow.com/questions/6314337/is-this-funktion-in-the-complexity/6314497#6314497 – Rob

2

Wenn false zurückgegeben wird, versucht der Algorithmus, die Potenzen aller Ganzzahlen x zu erhöhen, bis sie n überschreiten. Die Suche wird beendet, nachdem x = √n ausprobiert wurde.

Also für eine grobe Auswertung, nimmt die Befugnisse bis x^d = n Auswertung über log n/log x vervielfacht und x=2-x=√n wiederholt.

Daraus ergibt sich die Komplexität ist wie

log n.Sum(x=2 to √n)1/log x 

, die zu schätzen unbehaglich, sondern O(log n.√n) und Ω(√n).

Die pow Version nimmt log d multipliziert statt 1, um eine Leistung zu berechnen, vorausgesetzt es geschieht durch wiederholte Quadrierungen. Wie d = log n/log x ist die Komplexität wie

log n.Sum(x=2 to √n)(log log n - log log x)/log x 

noch schwerer zu schätzen, aber O(log n.log log n.√n) und Ω(√n).

Für den Bereich von n vom Typ int bedeckt, können Sie die pow Version zwischen einmal und fünfmal langsamer (es sei denn, die pow Funktion hat einen großen Overhead) erwarten.

+0

Summe (x = 2 bis √n) 1/log x ~ = √n/log (√n), also ist die Komplexität O (√ n). (http://mathforum.org/kb/message.jspa?messageID=89138 für Details der Summe). –

+0

@PaulHankin: danke. Das bestätigt O (log n.√n) und Ω (√ n).:) –

+1

Ich denke, es ist schön, hier eine enge Grenze zu finden, denn es motiviert die sorgfältigere Analyse, die Sie hier gemacht haben, und zeigt, dass der naive Ansatz der Annäherung in der anderen Antwort die falsche Antwort gibt. Wie auch immer, ich upvoted :) –

Verwandte Themen