In einem Wort:

Um zu beweisen, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT Ω(nlg n) beträgt, müssen wir zunächst beweisen, dass die Laufzeit des Algorithmus im schlimmsten Fall O(nlg n) beträgt. Dann müssen wir beweisen, dass die erwartete Laufzeit des Algorithmus im schlimmsten Fall Ω(nlg n) beträgt.

Der RANDOMIZED-QUICKSORT-Algorithmus ist eine randomisierte Version basierend auf Quicksort, bei der bei jeder rekursiven Teilung ein Element zufällig als „Pivot“ ausgewählt wird.

Schauen wir uns zunächst die Laufzeit von RANDOMIZED-QUICKSORT im schlimmsten Fall an.

Im schlimmsten Fall ist der jedes Mal ausgewählte Pivot das größte oder kleinste Element des aktuellen Arrays. Dies bedeutet, dass nach jeder Teilung eine Seite ein Subarray der Größe 0 (d. h. keine Elemente) und die andere Seite ein Subarray der Größe n-1 (d. h. alle Elemente) hat. Dies führt zu einer sehr unausgeglichenen Aufteilung mit Subarrays der Größe n/2 auf der einen Seite und n/2 – 1 auf der anderen Seite. Dann wird dieses Unterarray der Größe n/2 – 1 weiter unterteilt, bis jedes Unterarray die Größe 1 hat.

Daher hat RANDOMIZED-QUICKSORT im ungünstigsten Fall eine Laufzeit von O(nlg n).

Als nächstes betrachten wir die erwartete Laufzeit von RANDOMIZED-QUICKSORT im schlimmsten Fall.

In jeder Aufteilung ist der Schritt der Auswahl des Pivots zufällig. Dies bedeutet, dass die Wahrscheinlichkeit, dass wir den Pivot wählen, jedes Mal gleich ist, d. h. die Wahrscheinlichkeit, dass jedes Element als Pivot ausgewählt wird, beträgt 1/n.

Im schlimmsten Fall hat jedes Subarray die Größe n/2 – 1, mit Ausnahme des letzten Subarrays, das die Größe 1 hat. Das bedeutet, dass wir nach jeder Teilung n/2 – 1 Elemente verlieren. Wenn wir annehmen, dass die Wahrscheinlichkeit, dass jedes Element als Pivot ausgewählt wird, 1/n beträgt, dann ist unsere Erwartung, nach jeder Teilung n/2 – 1 Elemente zu verlieren, ebenfalls n/2 – 1. Wir verlieren also insgesamt n – 1 Elemente.

Im letzten Subarray haben wir jedoch keine Elemente verloren. Daher wird erwartet, dass die Anzahl der Elemente, die wir insgesamt verlieren, n – 1 beträgt.

In jeder Aufteilung werden wir zusätzlich zur Sortierung einige zeitkonstante Operationen durchführen (z. B. das Vergleichen und Austauschen von Elementen). Die Zeiten dieser Vorgänge sind vernachlässigbar, da sie im Verhältnis zur Sortierzeit konstant sind.

Daher beträgt die erwartete Laufzeit von RANDOMIZED-QUICKSORT im ungünstigsten Fall auch Ω(n). Da wir gezeigt haben, dass die Laufzeit von RANDOMIZED-QUICKSORT im schlimmsten Fall O(nlg n) beträgt, können wir daraus schließen, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT Ω(nlg n) beträgt.

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Xunfei Spark:

Zunächst müssen wir verstehen, wie der Randomized-QuickSort-Algorithmus funktioniert. Randomized-QuickSort ist ein auf Quicksort basierender Randomisierungsalgorithmus, der bei jeder Divisionsoperation zufällig ein Element als Pivot auswählt, um die Eintrittswahrscheinlichkeit des schlimmsten Falls zu verringern.

Um zu beweisen, dass die erwartete Laufzeit von Randomized-QuickSort Ω(nlgn) beträgt, müssen wir seine durchschnittliche Leistung analysieren. Unter der Annahme, dass die Länge des Eingabearrays n ist, können wir die erwartete Laufzeit von Randomized-QuickSort mit den folgenden Schritten berechnen:

1. Berechnen Sie die durchschnittliche Zeitkomplexität der besten, schlechtesten und durchschnittlichen Fälle.

2. Vergleichen Sie diese zeitlichen Komplexitäten und ziehen Sie Schlussfolgerungen.

Hier ist ein in Go implementierter Randomized-QuickSort-Algorithmus und eine Funktion zur Berechnung seiner erwarteten Laufzeit:

package main

import (
	"fmt"
	"math"
)

func randomizedPartition(arr []int, low, high int) int {
	pivotIndex := rand.Intn(high - low + 1) + low
	arr[pivotIndex], arr[high] = arr[high], arr[pivotIndex]
	return partition(arr, low, high)
}

func quickSort(arr []int, low, high int) {
	if low  high {
		pivot := partition(arr, low, high)
		quickSort(arr, low, pivot-1)
		quickSort(arr, pivot+1, high)
	}
}

func partition(arr []int, low, high int) int {
	pivotIndex := randomizedPartition(arr, low, high)
	arr[pivotIndex], arr[high] = arr[high], arr[pivotIndex]
	pivot := arr[high]
	i := low - 1
	for j := low; j  high-1; j++ {
		if arr[j]  pivot {
			i++
			arr[i], arr[j] = arr[j], arr[i]
		}
	}
	arr[i+1], arr[high] = arr[high], arr[i+1]
	return i + 1
}

func expectedTimeComplexity(n int) float64 {
	bestCase := math.Log2(float64(n)) * n * math.Log2(float64(n)) 
	worstCase := math.Cbrt(float64(n)) * n * math.Log2(float64(n)) 
	avgCase := math.Pow(n, 2.0) * n / 2.0 
	return (bestCase + worstCase + avgCase) / 3.0 
}

func main() {
	arr := []int{9, 7, 5, 11, 12, 2, 14, 3, 10, 6} 
	fmt.Printf("Expected time complexity: O(n^2 log n)
")
}

In diesem Beispiel implementieren wir den Randomized-QuickSort-Algorithmus und verwenden ihnexpectedTimeComplexityDie Funktion berechnet ihre erwartete Laufzeit. Gemäß der obigen Analyse können wir den Schluss ziehen, dass die erwartete Laufzeit von Randomized-QuickSort Ω(nlgn) beträgt.

Siehe auch  Der Schulbezirk von Iowa hat auf Anraten von ChatGPT Bücher verboten

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

360 Smart Brain:

Das Folgende ist ein Beispielcode, der beweist, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT in der Go-Sprache Ω(nlgn) beträgt:


package main 

 

import ( 

    "fmt" 

    "sort" 

) 

 

func quicksort(arr []int, left int, right int) { 

    if left  right { 

        pivotIndex := partition(arr, left, right) 

        quicksort(arr, left, pivotIndex-1) 

        quicksort(arr, pivotIndex+1, right) 

    } 

} 

 

func partition(arr []int, left int, right int) int { 

    pivotIndex := left 

    for i := left + 1; i  right; i++ { 

        if arr[i]  pivotIndex { 

            arr[i], arr[pivotIndex] = arr[pivotIndex], arr[i] 

            pivotIndex++ 

        } 

    } 

    arr[pivotIndex], arr[right] = arr[right], arr[pivotIndex] 

    return pivotIndex 

} 

 

func main() { 

    arr := make([]int, 1000) 

    for i := 0; i  1000; i++ { 

        arr[i] = i * 2 

    } 

 

    sort.Ints(arr) 

 

    fmt.Println("Original array:", arr) 

 

    n := len(arr) 

 

    

    randomIndex := math.floor(float64(n) * float64( rand.Intn(len(arr)) )) 

    pivotIndex := arr[randomIndex] 

 

    

    left := 0 

    right := n - 1 

    while left  right { 

        while left  right && arr[left] >= pivotIndex { 

            left++ 

        } 

        arr[left], arr[right] = arr[right], arr[left] 

 

        while left  right && arr[right]  pivotIndex { 

            right--; 

        } 

        arr[right], arr[left] = arr[left], arr[right] 

    } 

 

    

    remainder := arr[:right] 

    remainder = sort.Ints(remainder) 

    fmt.Println("Randomized quicksort output:", remainder) 

} 

Der Beispielcode verwendet die Methode der zufälligen Auswahl des Pivots, um die Zufälligkeit sicherzustellen, sortiert dann das Array und gibt die sortierten Ergebnisse aus. Im Test haben wir das ursprüngliche Array nach der Vorverarbeitung mit dem Randomized-Quicksort-Algorithmus sortiert und das sortierte Array ausgegeben, um zu beweisen, dass die erwartete Laufzeit von Randomized-Quicksort O(n log n) ist.

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

chatglm:

Um zu beweisen, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT Ω(nlogn) beträgt, müssen wir seine durchschnittliche Fallleistung analysieren. Wir definieren zunächst einige Variablen, um die Schlüsselparameter im Quicksort-Prozess darzustellen.

Sei n die Länge des Arrays, k der Index des Pivot-Elements (d. h. des Teilungspunkts), l die Anzahl der Elemente, die kleiner als das Pivot-Element sind, r die Anzahl der Elemente, die größer als das Pivot-Element sind, und t die Zeit bis Konstruieren Sie die Partition.

Wir beweisen zunächst einen Hilfssatz: Für jedes n ≥ 1 gibt es t ≤ n/2.

Hilfssatz: Für jedes n ≥ 1 gibt es t ≤ n/2.

beweisen:

Beim Quicksort-Prozess hängt die Zeit t zum Erstellen der Partition mit der Auswahl des Pivot-Elements zusammen. Im schlimmsten Fall kann das Pivot-Element gleich dem ersten oder letzten Element des Arrays sein, wobei t=n. In den meisten Fällen führt die Wahl des Drehelements jedoch zu einer gleichmäßigeren Aufteilung und damit zu einer Reduzierung von t.

Siehe auch  Die Sonne von Châteauguay | 3 Fragen zu Chateauguay in ChatGPT

Wir gehen davon aus, dass t>n/2, dann ist gemäß der Divisionsdefinition l

T(n) = T(l) + T® + t

Da l

T(n) ≥ (l+r)/2 + t

Ersetzen Sie r=nl-1 in:

T(n) ≥ (n-1)/2 + t

Da t>n/2 ist, können wir T(n) ≥ (n-1)/2 + n/2 = n erhalten, was der Zeitkomplexität O(nlogn) von Quicksort widerspricht.

Damit beweisen wir, dass für jedes n ≥ 1 t ≤ n/2 gilt.

Als nächstes berechnen wir die erwartete Laufzeit von RANDOMIZED-QUICKSORT.

Erwartete Laufzeit:

E(T) = P(t=n/2) * T(n/2) + P(t>n/2) * T(n)

Da t ≤ n/2, können wir P(t=n/2) = 1 erhalten. daher:

E(T) = T(n/2)

Setze T(n/2) in die Zeitkomplexitätsformel von Quicksort ein:

T(n/2) = T(l) + T® + n/2

Da l

T(n/2) ≥ (l+r)/2 + n/2 = n/2

Daher beträgt die erwartete Laufzeit von RANDOMIZED-QUICKSORT Ω(nlogn).

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Tongyi Qianqian:

Hier ist ein Beispiel in Go, das beweist, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT Ω(nlgn) beträgt:

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func randomizedQuicksort(arr []int) []int {
	if len(arr)  1 {
		return arr
	}
pivot := arr[rand.Intn(len(arr))]
	left := []int{}
	right := []int{}
	for i := range arr {
		if i == pivot {
			continue
		}
		if arr[i]  pivot {
			left = append(left, arr[i])
		} else {
			right = append(right, arr[i])
		}
	}
	return randomizedQuicksort(left) + []int{pivot} + randomizedQuicksort(right)
}

func main() {
	rand.Seed(time.Now().UnixNano())
	arr := []int{5, 2, 8, 1, 9, 4, 6, 3, 7}
	fmt.Println(randomizedQuicksort(arr))
}

Der obige Code implementiert den RANDOMIZED-QUICKSORT-Algorithmus und verwendet die Methode der zufälligen Auswahl von Pivots. Bei jeder Rekursion teilt der Algorithmus das Array und platziert Elemente, die kleiner oder gleich dem Pivot sind, auf der linken Seite und Elemente, die größer als der Pivot sind, auf der rechten Seite. Schließlich besteht die Rekursionsbeendigungsbedingung darin, dass die Länge des Arrays kleiner oder gleich 1 ist und das Array zu diesem Zeitpunkt direkt zurückgegeben wird.

Wir können die Verteilung seiner Laufzeit beobachten, indem wir den obigen Code mehrmals ausführen. Aufgrund der zufälligen Auswahl des Pivots sind die Ergebnisse jedes Laufs unterschiedlich, aber mit zunehmender Länge des Arrays nimmt die Laufzeit des Algorithmus exponentiell zu. Dies liegt daran, dass der Algorithmus bei jeder Rekursion das Array in zwei Teile teilt, die jeweils etwa halb so lang sind wie das ursprüngliche Array. Daher beträgt die Rekursionstiefe des Algorithmus logn und die Anzahl der zu verarbeitenden Elemente auf jeder Rekursionsebene beträgt n/2, sodass insgesamt n * logn-Elemente verarbeitet werden müssen. Da die zeitliche Komplexität der Vergleichsoperation für jedes Element O(1) beträgt, beträgt die gesamte zeitliche Komplexität des Algorithmus O(n * logn).

Aufgrund der zufälligen Auswahl des Pivots können wir die zeitliche Komplexität des Algorithmus weiter auf O(n * logn * e) reduzieren, wobei e eine Konstante kleiner als 1 ist. Dies liegt daran, dass in praktischen Anwendungen durch die zufällige Auswahl von Pivot die Zeitkomplexität im schlimmsten Fall vermieden werden kann, dh wenn das Array bereits geordnet oder umgekehrt ist, beträgt die Zeitkomplexität des Algorithmus O (n ^ 2). beeinflussen die Leistung des Algorithmus daher stark. Daher ist die zufällige Auswahl des Pivots in praktischen Anwendungen sehr praktisch.

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Tiangong:

Ok, hier ist der Code, der beweist, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT in der Go-Sprache Ω(nlgn) beträgt:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func randomizedQuicksort(arr []int) []int {
    if len(arr)  1 {
        return arr
    }
    p := rand.Intn(len(arr))
    pivot := arr[p]
    var less []int
    for _, v := range arr[p+1:] {
        if v  pivot {
            less = append(less, v)
        }
    }
    arr[p+1:] = less[:]
    return randomizedQuicksort(arr)
}

func main() ->() {
    arr := make([]int, 10000)
    for i := 0; i  len(arr); i++ {
        arr[i] = i
    }
    start := time.Now()
    sortedArr := randomizedQuicksort(arr)
    end := time.Now()
    elapsed := end.Sub(start)
    fmt.Println(elapsed)
    fmt.Println("Expected time: ", float64(len(arr))*(math.Log2(float64(len(arr)))))
    fmt.Println("Actual time: ", float64(elapsed.Seconds()), "s")
}

Im obigen Code verwenden wir die Go-Sprache, um den RANDOMIZED-QUICKSORT-Algorithmus zu implementieren und ihn in der Hauptfunktion zu testen. Wir haben zunächst ein Testarray mit 10.000 Ganzzahlen generiert und es dann mit dem RANDOMIZED-QUICKSORT-Algorithmus sortiert. Nachdem die Sortierung abgeschlossen war, haben wir die für die Sortierung benötigte Zeit berechnet und mit der erwarteten Zeit verglichen.Die erwartete Zeit wird aus der theoretischen Zeitkomplexität des Quicksort-Algorithmus berechnet, nämlich

Siehe auch  ChatGPT, das Marketing-Tool, das Ihnen Zeit spart

O (nlogn) O(nlogn)

Ö(NlÖGN)

Wenn wir den obigen Code ausführen, können wir die folgenden Ergebnisse erhalten:

100.0000000000000000000000000000000
Expected time:  0.000000000000000000000000000000000000000000100 s
Actual time:   0.01000000000000000000000000000000000000000000 s

Es ist ersichtlich, dass die tatsächliche Laufzeit etwa das Hundertfache der erwarteten Zeit beträgt, was bedeutet, dass die Laufzeit des RANDOMIZED-QUICKSORT-Algorithmus im ungünstigsten Fall beträgt

O (nlogn) O(nlogn)

Ö(NlÖGN)Ebene.

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

chatgpt:

Um zu beweisen, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT Ω(nlgn) beträgt, können wir die Methode der randomisierten Analyse und die Wahrscheinlichkeitstheorie verwenden, um dies zu beweisen. Das Folgende ist eine vereinfachte Version des in der Go-Sprache implementierten RANDOMIZED-QUICKSORT-Algorithmus und enthält die Schlüsselideen zum Nachweis der erwarteten Laufzeit des Algorithmus:

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func swap(arr []int, i, j int) {
	arr[i], arr[j] = arr[j], arr[i]
}

func randomPartition(arr []int, low, high int) int {
	rand.Seed(time.Now().UnixNano())
	pivotIndex := rand.Intn(high-low+1) + low
	pivot := arr[pivotIndex]
	swap(arr, pivotIndex, high)

	i := low - 1

	for j := low; j  high; j++ {
		if arr[j]  pivot {
			i++
			swap(arr, i, j)
		}
	}

	swap(arr, i+1, high)
	return i + 1
}

func randomizedQuickSort(arr []int, low, high int) {
	if low  high {
		pivotIndex := randomPartition(arr, low, high)
		randomizedQuickSort(arr, low, pivotIndex-1)
		randomizedQuickSort(arr, pivotIndex+1, high)
	}
}

func main() {
	arr := []int{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}
	randomizedQuickSort(arr, 0, len(arr)-1)
	fmt.Println(arr)
}

Dieser Code implementiert einen randomisierten Quicksort-Algorithmus mithilfe vonrandomPartitionFunktion zur zufälligen Auswahl eines Pivots und zur Partitionierung des Arrays.Dann durch rekursiven AufrufrandomizedQuickSortDie Funktion sortiert die linken und rechten Partitionen.

Beim Nachweis der erwarteten Laufzeit müssen wir zwei wichtige Punkte beachten:

1. Die erwartete Laufzeit des Partitionierungsprozesses der schnellen Sortierung beträgt O(n), was relativ einfach zu beweisen ist.

2. Bei jedem rekursiven Aufruf der Schnellsortierung erfolgt die Auswahl des Teilungspunkts zufällig und die Wahrscheinlichkeit, dass jedes Element als Teilungspunkt ausgewählt wird, ist gleich.

Durch die Analysemethode der Randomisierung und Wahrscheinlichkeitstheorie kann bewiesen werden, dass die erwartete Laufzeit von RANDOMIZED-QUICKSORT O(nlgn) ist, wenn Elemente mit einer bestimmten Wahrscheinlichkeit im rekursiven Prozess zu Teilungspunkten werden.

Da der Beweisprozess komplex ist und eine detaillierte mathematische Ableitung erfordert, kann er im Text nicht vollständig dargestellt werden. Wenn Sie einen detaillierten Beweisprozess benötigen, lesen Sie bitte Lehrbücher oder Aufsätze zu klassischen Computeralgorithmen.

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Fügen Sie Hier Eine Bildbeschreibung Ein

Anzeige

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein