Was ist die zeitliche Komplexität dieses Algorithmus? Und warum?

8

Ich bin festgefahren, wenn ich die zeitliche Komplexität des folgenden Algorithmus analysiere:

def fun (r, k, d, p):
    if d > p:
        return r
    if d = 0 and p = 0:
        r <- r + k
        return r
    if d > 0:
        fun (r, k + 1, d - 1, p)
    if p > 0:
        fun (r, k - 1, d, p - 1)

Der Root-Aufruf wird fun (0, 0, n, n)und nist die Größe des Problems.

Ich denke das: Die Wiederholungsrelation ist T(n,n)=T(n1,n)+T(n,n1) , was T(2n)=2T(2n1)T(m)=2T(m1) und somitO(2m)O(4n) .

Ist meine Analyse korrekt (ich weiß, dass sie nicht sehr vollständig und genau ist)? Wenn es einen schwerwiegenden Fehler gibt, weisen Sie bitte darauf hin oder zeigen Sie mir einen korrekten und vollständigen Beweis für die zeitliche Komplexität dieses Algorithmus.

象 嘉 道
quelle
1
xando, ich ermutige Sie, die Frage zu bearbeiten, um zu erklären, warum die Standardtechniken nicht funktionieren: Erklären Sie, warum sie fehlschlagen. (Cc: @YuvalFilmus) Erhalten Sie beispielsweise eine Wiederholungsbeziehung, die schwer zu lösen ist, und wenn ja, welche Wiederholung erhalten Sie?
DW
1
In Kommentaren mit Polyergic habe ich festgestellt, dass der Pseudocode unklar ist: Es ist nicht klar, was Sie mit dem Algorithmus meinen, wenn sowohl d>0als auch p>0. Sie zeigen nicht, was die Funktion zurückgibt, wenn wir die 3. und 4. if-Anweisung erreichen. Wollten Sie returnnach jedem rekursiven Aufruf von eine Anweisung haben fun? (Wollten Sie fun (r, k + 1, d - 1, p)es sein return fun (r, k + 1, d - 1, p)?) Oder wollten Sie eine returnAussage ganz am Ende des Funktionskörpers haben? Bitte bearbeiten Sie Ihren Pseudocode, um zu verdeutlichen und sicherzustellen, dass Sie zeigen, was dies in allen möglichen Fällen zurückgibt.
DW
Um es auf eine andere Weise: annehmen d<=pund d>0und p>0alle halten. Was soll passieren? Führt der Algorithmus zwei rekursive Aufrufe der Funktion durch? Oder ruft es rekursiv auf fun(r, k + 1, d - 1, p)und kehrt dann sofort zurück, ohne rekursiv aufzurufen fun(r, k - 1, d, p - 1)? Wenn ich Ihren Pseudocode wörtlich nehme, scheint es, dass er zwei rekursive Aufrufe ausführt und dann mit einem undefinierten Rückgabewert zurückkehrt - aber das scheint seltsam und lässt mich fragen, ob der Pseudocode einen Tippfehler enthält.
DW

Antworten:

10

dpd,p0dp(d,p)(d1,p),(d,p1)Vermeiden von Paaren, die die oben angegebenen Einschränkungen ungültig machen.

(0,0)pddpn(2nn)/(n+1)=Θ(4n/n3/2)

Um eine Obergrenze zu erhalten, beachten Sie, dass wir auf dem Weg zu jedem Blatt durch Knoten gehen und dies eine Obergrenze ergibt, die größer ist als die Untergrenze, dh .2 n Θ ( 4 n / 2n2nΘ(4n/n)

Wir haben eine Untergrenze von und eine Obergrenze von . Was sind die genauen Asymptotika? Sie wachsen wie die Gesamtzahl der Pfade, die die X-Achse nicht kreuzen und höchstens Schritte in jede Richtung aufweisen. Unter Verwendung des Wahlsatzes von Bertrand können wir einen genauen Ausdruck dafür erhalten: Es bleibt also, diese Summe asymptotisch zu schätzen: O ( 4 n / Ω(4n/n3/2)n Σ 0 d p N p - d + 1O(4n/n)n

0dpnpd+1p+1(p+dp).
0dpn(p+dp)0dpndp+1(p+dd)=0dpn(p+dp)0dpn(p+dp+1)=p=0n(2p+1p+1)p=0n(2p+1p+2)=p=0n1p+1(2p+2p)=Θ(p=0n4pp3/2)=Θ(4nn3/2).
Yuval Filmus
quelle
1
Ich mag Ihren geometrischen Ansatz mit diesen "Schritten" sehr. Ist das eine übliche Technik? Ich habe es noch nie gesehen.
Andreas T
@AndreasT Ich würde es nicht als übliche Technik bezeichnen, normalerweise trifft es nicht zu. Hier ist die kombinatorische Interpretation ziemlich offensichtlich und führt zu einer solchen Lösung.
Yuval Filmus
0

Von Fall zu Fall:

  1. d> p : Konstante Zeit
  2. d = 0 ∧ p = 0 : Konstante Zeit
  3. d> 0 : Man beachte, dass d ≯ p ist, also haben wir 0 <d ≤ p und funrekursiert auf d-1 bis d ≯ 0; da p> 0 ist, ist dies in d + linear (Fall 4) .
  4. p> 0 : Man beachte, dass d ≯ 0 ist, also haben wir d ≤ 0 ≤ p (mit d <p) und funrekursiv auf p-1 bis p ≯ 0; Dies ist linear in p + (einer von Fall 1, 2 oder 5).
  5. d ≤ p <0 : undefiniert; Ich gehe davon aus, dass dies konstante Zeit ist

Beginnend mit d = p = n> 0 trifft Fall 3, gefolgt von Fall 4. Wenn n eine ganze Zahl ist, ist der letzte Fall 2, andernfalls ist der letzte Fall 5. Die Gesamtzeit für diese Fälle ist d + p +1 oder 2n + 1.

ShadSterling
quelle
2n. Ich denke, Sie haben abgelehnt, weil ich mich auf die Argumentation konzentriert habe?
ShadSterling
1
Vielen Dank für die Bearbeitung der Antwort! Das Rätsel ist nun, dass Sie zu dem Schluss gekommen sind, dass die Laufzeit , aber Yuval zu dem Schluss gekommen ist, dass die Laufzeit in exponentiell ist . Das ist ein ziemlich wesentlicher Unterschied. nO(n)n
DW
1
Hmm, ich denke, ich habe die Pseudocodes ifals "mach eine davon" genommen, während @Yuval sie als "jede dieser in der richtigen Reihenfolge betrachten" nahm. Letzteres ist natürlich das, was ifs (ohne else) im tatsächlichen Code bedeutet; Ich bin an Ersteres in fast jedem anderen Kontext als dem eigentlichen Code gewöhnt (auch im Pseudocode, obwohl die Verwendung im Pseudocode inkonsistent ist).
ShadSterling
Ich verstehe was du meinst. Das Fehlen von returnAnweisungen in der zweiten Hälfte des Codes macht dies ziemlich verwirrend.
DW