Was sind die Eigenschaften eines

19

Manchmal ist es einfach, die zeitliche Komplexität eines Algorithmus zu erkennen, wenn ich ihn sorgfältig untersuche. Algorithmen mit zwei verschachtelten Schleifen von N sind offensichtlich N2 . Algorithmen , die alle möglichen Kombinationen von explore N Gruppen von zwei Werten ist offensichtlich 2N .

Ich weiß jedoch nicht, wie ich einen Algorithmus mit Θ(NlogN) -Komplexität "erkennen" soll . Eine rekursive Mergesort-Implementierung ist beispielsweise eine. Was sind die gemeinsamen Merkmale von Mergesort- oder anderen Θ(NlogN) -Algorithmen, die mir einen Hinweis geben, wenn ich einen analysiere?

Ich bin mir sicher, dass es mehr als eine Möglichkeit gibt, wie ein Algorithmus von Komplexität sein kann. Daher sind alle Antworten willkommen. Übrigens suche ich allgemeine Eigenschaften und Tipps, keine strengen Beweise.Θ(NlogN)

Barry Fruitman
quelle
6
bedeutet Baum. O(logn)
Pratik Deoghare
2
@PratikDeoghare: Nicht unbedingt.
Raphael
3
@Raphael meinte ich meistens! :)
Pratik Deoghare

Antworten:

17

Ihr archetypisches ist ein Divide-and-Conquer- Algorithmus, der die Arbeit in linearer Zeit aufteilt (und neu kombiniert) und über die Teile rekursiert. So funktioniert das Sortieren beim Zusammenführen: O ( n ) Zeit damit verbringen , die Eingabe in zwei ungefähr gleiche Teile zu teilen, jedes Teil rekursiv zu sortieren und Θ ( n ) Zeit damit zu verbringen , die beiden sortierten Hälften zu kombinieren.Θ(nlogn)O(n)Θ(n)

Intuitiv setzt sich die Idee der Teilung und Eroberung fort und jede Teilungsstufe benötigt insgesamt eine lineare Zeit, da die Zunahme der Anzahl der zu teilenden Teile genau der Abnahme der Größe der Teile entspricht, da die durch die Teilung benötigte Zeit linear ist. Die Gesamtlaufzeit ergibt sich aus den Gesamtkosten einer Teilungsstufe multipliziert mit der Anzahl der Teilungsstufen. Da sich die Größe der Teile zu jedem Zeitpunkt halbiert, gibt es Teilungsstufen, so dass die Gesamtlaufzeit n log ( n ) beträgt . (Bis auf eine multiplikative Konstante ist die Basis des Logarithmus irrelevant.)log2(n)nlog(n)

Um die Laufzeit eines solchen Algorithmus in Gleichungen () umzurechnen, kann man sie rekursiv ausdrücken: T ( n ) = 2 T ( n / 2 ) + Θ ( n ) . Es ist klar, dass dieser Algorithmus mehr als lineare Zeit benötigt, und wir können sehen, wie viel mehr, wenn wir durch n dividieren : T ( n )T(n)T(n)=2T(n/2)+Θ(n)n Wennn sichverdoppelt, nimmtT(n)/num einen konstanten Betrag zu:T(n)/nnimmt logarithmisch zu, oder mit anderen Worten,T(n)=Θ(nlogn).

T(n)n=T(n/2)n/2+Θ(1)
nT(n)/nT(n)/nT(n)=Θ(nlogn)

Dies ist ein Beispiel für ein allgemeineres Muster: den Hauptsatz . Für jeden rekursive Algorithmus, der unterteilt ihre Eingabe der Größe in ein Stück mit einer Größe n / b , und nimmt eine Zeit f ( n ) die Spaltung und Rekombination, die Laufzeit genügt auszuführen T ( n ) = ein T ( n / b ) + f ( n ) . Dies führt zu einer geschlossenen Form, die von den Werten von a und b und der Form von abhängtnan/bf(n)T(n)=aT(n/b)+f(n)ab . Wenn a = b und f ( n ) = Θ ( n ) ist , besagt der Hauptsatz, dass T ( n ) = Θ ( n log n ) ist .fa=bf(n)=Θ(n)T(n)=Θ(nlogn)

Gilles 'SO - hör auf böse zu sein'
quelle
1
To summarise: algorithms that do away with constant fractions of the search space at a time will exhibit logarithmic terms. The other factors depend on how long it takes to perform the doing away.
Raphael
1
example: quicksort average case O(nlogn)
vzn
11

Two other categories of algorithms that take Θ(nlogn) time:

Algorithms where each item is processed in turn, and it takes logarithmic time to process each item (e.g. HeapSort or many of the plane sweep computational geometry algorithms).

Algorithms where the running time is dominated by a sorting pre-processing step. (For example, in Kruskal's algorithm for minimum spanning tree, we may sort the edges by weight as the first step).

Joe
quelle
Upvoted for the first paragraph. The second seems redundant, since the linearithmic sorting algorithms we know are either divide & conquer or heapsort. An example for the first category is search of n objects in a binary search tree (or sorted array) of size n; on a more abstract level, that can also be seen as divide & conquer, though.
Raphael
@Raphael I know that sorting is redundant with the categories of running times already given. The point is that sorting is sometimes the "bottleneck" and algorithms where at first blush the question isn't about sorting may still have the run-time because sorting is required.
Joe
9

Eine andere Kategorie: Algorithmen, in denen die Ausgabe Größe hatΘ(nlogn), and therefore Θ(nlogn) running time is linear in the output size.

Although the details of such algorithms often use divide-and-conquer techniques, they don't necessarily have to. The run-time fundamentally comes from the question being asked, and so I think it is worth mentioning separately.

This comes up in data structures which are based on an augmented binary search tree, where each node stores a linear size data structure to search over the leaves in that node's subtree. Such data structures come up often in geometric range searching, and are often based on a decomposition scheme. See Agarwal's Survey.

For a concrete example, consider the range-tree, built to answer two dimensional orthogonal range queries. Although the space was later reduced using some compression techniques to pack multiple objects into a single word, the textbook (and most intuitive) version of the data structure requires O(nlogn) space (each leaf is stored in an auxiliary structure at each node on the path from the leaf to the root, or in O(logn) places), and the construction algorithm takes time linear in the space requirement.

Joe
quelle
An example would be finding the n-th prime using a sieve, because you'd need a sieve of size θ(nlogn).
gnasher729
6

A complexity of O(nlogn) arises from divide and conquer algorithms which divide their input into k pieces of roughly equal size in time O(n), operate on these pieces recursively, and then combine them in time O(n). If you only operate on some of the pieces, the running time drops to O(n).

Yuval Filmus
quelle
5

Those are typically algorithms of the "divide and conquer" variety, where the cost of dividing and combining subsolutions isn't "too large". Take a look at this FAQ to see what kinds of recurrences give rise to this behaviour.

vonbrand
quelle
3

Typically, Divide-and-conquer algorithms will yield O(N log N) complexity.

Brent Hronik
quelle
-1

A generic example of a loop (not an algorithm per se) that runs in O(nlogn) is the following:

for (i = 0; i < constant; i++){
    for(j = 0; j < n; j++){
        // Do some O(1) stuff on the input
    }
}

// Alternative Variant:
for (i = 0; i < constant; i++){
    for(j = n; j < constant; j++){
        // Do some O(1) stuff on the input
    }
}

(note that this nested loops are not O(n2). Also note that it isn't divide-and-conquer nor recursive.)

I can't give a concrete example of an algorithm that uses this loop, but it comes up often when coding custom algorithms.

Nicolas Miari
quelle
Yes, these are both O(nlogn) but for the trivial reason that the bound is not tight. The first one is Θ(n) and the second is Θ(1) (or Θ(|n|) if n can be negative).
David Richerby
I thought it useful to mention, since it does come up in practice but every search for "O(nlogn)" is mostly "divide-and-conquer" examples like e.g. merge sort.
Nicolas Miari
additionally, the original question didn't ask for big-theta.
Nicolas Miari
1
Sure but any algorithm that runs in linear or constant time is O(nlogn), as well as being O(22n) and O(almost anything else). Your answer has nothing to do with logarithms. If you want to make the point that the question should be asking about Θ(nlogn) rather than O(nlogn) then either make that point explicitly as comment to the question or, even better, edit the question.
David Richerby
I wanted to make the point that I actually searched the internet for O(nlogn) to see if the loop in my answer, that I had to come up with for an actual answer to an actual programming problem that was required to run in O(nlogn), was actually O(nlogn) or not. And most information around deals with divide-and-conquer algorithms, so it would be worth mentioning. I do not pretend my answer to be the archetypical O(nlogn) algorithm.
Nicolas Miari