Heim häufiges Problem lineare Zeitauswahl

lineare Zeitauswahl

Jun 20, 2019 am 11:07 AM
时间 线性

lineare Zeitauswahl

Definition: Gegeben n Elemente in einer linearen Folge und eine ganze Zahl k, 1≤k≤n, ist es erforderlich, das k-kleinste unter diesen n Elementen zu finden Elemente.

(1) In einigen Sonderfällen ist es einfach, einen linearen Zeitalgorithmus zu entwerfen, um das Auswahlproblem zu lösen. Wenn Sie beispielsweise das größte oder kleinste Element auswählen möchten, kann dies natürlich in O(n)-Zeit erfolgen. (Nur ein Vergleich)

(2) Das allgemeine Auswahlproblem, insbesondere das Auswahlproblem des Medians, scheint schwieriger zu sein als das kleinste (große) Element. Tatsächlich sind sie jedoch im Sinne der asymptotischen Ordnung gleich. Dies kann auch in O(n)-Zeit erfolgen.

Lineare Zeitauswahlmethode eins: randomizedSelect

Idee: Zufällige Schnellsortierung anpassen, anstatt das gesamte Array zu sortieren, aber die ausgewählte Sortierung ( Schneller)

Zeitkomplexität:

(1) Im schlimmsten Fall benötigt der Algorithmus randomizedSelect O(n^2) Berechnungszeit

z . Wir müssen das kleinste Element finden, aber die Position, die wir bei jeder Division durch die Partitionsfunktion erhalten, ist immer sehr groß (nahe bei n) (das heißt, sie wird immer am größten Element geteilt)

( 2) aber es kann Es ist bewiesen, dass der Algorithmus randomizedSelect das k-kleinste Element unter n Eingabeelementen in der durchschnittlichen Zeit von O(n) finden kann.

Der Code lautet wie folgt:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int Partition(int a[],int p,int r){
    int i=p,j=r+1,x=a[p];
    while(1){
        while(a[++i]<x&&i<r);
        while(a[--j]>x);
        if(i>=j)break;
        swap(a[i],a[j]);
    }
    a[p]=a[j];
    a[j]=x;
    return j;
}

int RandomizedPartition(int a[],int p,int r){
    int i=rand()%(r-p)+p;
    swap(a[p],a[i]);
    return Partition(a,p,r);
}

int RandomizedSelect(int a[],int p,int r,int k){
    if(p==r)return a[p];
    int i=RandomizedPartition(a,p,r);//返回基准元素的位置
    int j=i-p+1;//表示基准元素及其左边一共多少个元素
    if(k<=j)RandomizedSelect(a,p,i,k);
    else RandomizedSelect(a,i+1,r,k-j);
}
int main(){
    int a[10]={3,1,7,6,5,9,8,2,0,4};
    int x;
    while(scanf("%d",&x)!=EOF){
        int ans=RandomizedSelect(a,0,9,x);
        printf("%d\n",ans);
    }
}
Nach dem Login kopieren

Lineare Zeitauswahlmethode zwei:

Wenn Sie a<🎜 in linearer Zeit finden können >Teilungsbasis, sodass die Länge der beiden gemäß dieser Basis geteilten Unterarrays mindestens das ε-fache der Länge des ursprünglichen Arrays beträgt (0<ε<1 ist eine bestimmte positive Konstante). Es kann im schlimmsten Fall verwendet werden. Es dauert O(n) Zeit, die Auswahlaufgabe abzuschließen.

Wenn beispielsweise ε=9/10, wird die Länge des durch den rekursiven Aufruf des Algorithmus erzeugten Subarrays um mindestens 1/10 verkürzt. Daher erfüllt die vom Algorithmus benötigte Berechnungszeit T(n) im schlimmsten Fall die rekursive Formel T(n)≤T(9n/10)+O(n). Daraus können wir T(n)=O(n) erhalten.

Als der Lehrer darüber sprach, betonte er, dass „finden“ und nicht „finden“ bedeutet, den Median zu finden Wir wollen den Wert und unsere vorherige Schnellsortierung usw. bestanden darin, die Position des Werts zu bestimmen, das heißt, das Referenzelement an der richtigen Position zu platzieren.

Schritte:

(1) Teilen Sie n Eingabeelemente jeweils in n/5 (aufgerundete) Gruppen auf Die Gruppe enthält 5 Elemente, und es kann höchstens eine Gruppe geben, die nicht 5 Elemente enthält. Verwenden Sie einen beliebigen Sortieralgorithmus, um die Elemente in jeder Gruppe zu sortieren und den Median jeder Gruppe zu ermitteln, insgesamt n/5 (aufgerundet).

(2) Rufen Sie rekursiv „select“ auf, um den Median dieser

n/5 (aufgerundet) Elemente zu ermitteln. Wenn n/5 (aufgerundet)

eine gerade Zahl ist, ermitteln Sie den größeren ihrer beiden Mediane. Verwenden Sie dieses Element als Grundlage für die Division.

Schematische Darstellung der Partitionierungsstrategie:

Weißer Punkt: Median jeder Gruppe; Punkt x: Median des Medians

Beispiel: lineare Zeitauswahl

Suchen Sie in aufsteigender Reihenfolge das folgende Das 18. Element von 29 Elemente: 8,31,60,33,17,4,51,57,49,35,11,43,37,3,13,52,6,19,25,32, 54,16,5,41,7,23,22,46,29.(1) Teilen Sie die ersten 25 Elemente in 5 (=floor(29/5)) Gruppen: (8,31,60, 33 ,17),(4,51,57,49,35),(11,43,37,3,13),(52,6,19,25,32),(54,16,5,41, 7 );(2) Extrahieren Sie das Medianelement jeder Gruppe, um die Menge {31,49,13,25,16} zu bilden;(3) Verwenden Sie den Algorithmus rekursiv, um den Median der Menge zu ermitteln, Erhalten m=25;

(4) Teilen Sie die 29 Elemente gemäß m=25 in 3 Unterarrays (in der ursprünglichen Reihenfolge)

P={8,17,4,11, 3,13,6 ,19 ,16,5,7,23,22}
Q={25}

R={31,60,33,51,57,49,35,43,37,52, 32, 54,41,46,29}

(5) Da |P|=13,|Q|=1,k=18, also P und Q aufgeben und k=18-13-1 = machen 4, führe diesen Algorithmus rekursiv auf R aus; 52},{32,54,41,46,29}
(7) Finden Sie das Medianelement dieser drei Gruppen von Elementen: {51,43,41}, das Medianelement dieser Menge ist 43;
(8) Teilen Sie R in 3 Gruppen basierend auf 43 auf:

{31, 33, 35,37,32, 41, 29},{43},{60, 51,57 , 49, 52, 54, 46}


Komplexität:

Angenommen, die Array-Länge beträgt n

Wenn n <75, beträgt die vom Algorithmus verwendete Berechnungszeit einen bestimmten Wert nicht Konstante C1

Wenn n≥75, wird die for-Schleife n/5-mal ausgeführt und benötigt jedes Mal eine bestimmte Konstante (eine feste Zahl soll unter 5 gesucht werden!); Die Länge beträgt 1/5 der ursprünglichen Länge. Die benötigte Zeit kann als T(n/5) aufgezeichnet werden. Nach der Teilung enthält das erhaltene Array höchstens 3n/4 Elemente und die benötigte Zeit wird als T(3n/4) aufgezeichnet ). T(n) kann also rekursiv ausgedrückt werden als:

Die Lösung für diesen rekursiven Ausdruck ist T(n)=O(n)

上述算法将每一组的大小定为5,并选取75作为是否作递归调用的分界点(大于75使用该算法)。这2点保证了T(n)的递归式中2个自变量之和n/5+3n/4=19n/20=εn,0<ε<1。这是使T(n)=O(n)的关键之处。当然,除了5和75之外,还有其他选择。

注意:

(1)设中位数的中位数是x,比x小和比x大的元素至少3*(n-5)/10个,原因:

3*(n/5-1)*1/2

3---中位数比x小的每一组中有3个元素比x小

n/5-1---有5个数的组数

1/2---大概有1/2组的中位数比x小

(2)而当n≥75时,3(n-5)/10≥n/4所以按此基准划分所得的2个子数组的长度都至少缩短1/4,也就是说,长度最长为原长度的3/4。

lineare Zeitauswahl

如图,划分的部分左上是肯定比x小的(大概占1/4)右下是肯定比x大的(大概占1/4)左下和右上不确定,就算这两部分同时不比x小或比x大,划分成的子区间也能至少缩短1/4!

核心代码:

Type Select(Type a[], int p, int r, int k)
{
      if (r-p<75) {
        //用某个简单排序算法对数组a[p:r]排序;
        return a[p+k-1];
        };
      for (int i=0;i<=(r-p-4)/5;i++)//i即为n个元素的分组个数
      //将a[p+5*i]至a[p+5*i+4]的第3小元素与a[p+i]交换位置;
      //将中位数元素换至前面
  
      //找中位数的中位数,r-p-4即上面所说的n-5
      Type x=Select(a,p,p+(r-p-4)/5,(r-p-4)/10);//x是中位数的中位数
      int i=Partition(a,p,r,x),j=i-p+1;//i为快排一趟找到区间[p,r]中x应该在的位置,j为[p,i]区间的元素个数
      if (k<=j) return Select(a,p,i,k);
      else return Select(a,i+1,r,k-j);
}
Nach dem Login kopieren

关键的代码是:

for ( int i = 0; i<=(r-p-4)/5; i++ )//i即为n个元素的分组个数
      //将a[p+5*i]至a[p+5*i+4]的第3小元素与a[p+i]交换位置;
      //将中位数元素换至前面
Nach dem Login kopieren

一共(r-p+1)/5个组

注意这里i从0开始表示,为了方便交换时带入数组的下标,0-(r-p-4)/5,即一共(r-p-4)/5+1各组,即(r-p+1)/5个组

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;

void bubbleSort(int a[],int p,int r){
    for(int i=p;i<r;i++){
        for(int j=i+1;j<=r;j++){
            if(a[j]<a[i])swap(a[i],a[j]);
        }
    }
}

int Partition(int a[],int p,int r,int val){
    int pos;
    for(int q=p;q<=r;q++){
        if(a[q]==val){pos=q;break;}
    }
    swap(a[p],a[pos]);

    int i=p,j=r+1,x=a[p];
    while(1){
        while(a[++i]<x&&i<r);
        while(a[--j]>x);
        if(i>=j)break;
        swap(a[i],a[j]);
    }
    a[p]=a[j];
    a[j]=x;
    return j;
}

int Select(int a[],int p,int r,int k){
    if(r-p<75){
        bubbleSort(a,p,r);
        return a[p+k-1];
    }

    for(int i=0;i<=(r-p-4)/5;i++){//把每个组的中位数交换到区间[p,p+(r-p-4)/4]
        int s=p+5*i,t=s+4;
        for(int j=0;j<3;j++){//冒泡排序,从后开始排,结果使得后三个数是排好顺序的(递增)
            for(int n=s;n<t-j;n++){
                if(a[n]>a[n+1])swap(a[n],a[n-1]);
            }
        }
        swap(a[p+i],a[s+2]);//交换每组中的中位数到前面
    }
    //(r-p-4)/5表示组数-1,则[p,p+(r-p-4)/5]的区间长度等于组数
    int x=Select(a,p,p+(r-p-4)/5,(r-p-4)/10);//求中位数的中位数
    int i=Partition(a,p,r,x),j=i-p+1;
    if(k<=j)return Select(a,p,i,k);
    else return Select(a,i+1,r,k-j);
}
int main(){
    int x;
    //数组a存了0-79
    int a[80]={3,1,7,6,5,9,8,2,0,4,
               13,11,17,16,15,19,18,12,10,14,
               23,21,27,26,25,29,28,22,20,24,
               33,31,37,36,35,39,38,32,30,34,
               43,41,47,46,45,49,48,42,40,44,
               53,51,57,56,55,59,58,52,50,54,
               63,61,67,66,65,69,68,62,60,64,
               73,71,77,76,75,79,78,72,70,74,
              };
    while(scanf("%d",&x)!=EOF){
        printf("第%d大的数是%d\n",x,Select(a,0,79,x));
    }
}
Nach dem Login kopieren

qwq,博主nc写错输出了,“第i小的数”

lineare Zeitauswahl

更多常见问题的相关技术文章,请访问常见问题教程栏目进行学习!

Das obige ist der detaillierte Inhalt vonlineare Zeitauswahl. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat -Befehle und wie man sie benutzt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Wie viel kostet ein Douyin-Lichtschild der Stufe 10? Wie viele Tage dauert es, ein Fanschild der Stufe 10 zu erstellen? Wie viel kostet ein Douyin-Lichtschild der Stufe 10? Wie viele Tage dauert es, ein Fanschild der Stufe 10 zu erstellen? Mar 11, 2024 pm 05:37 PM

Auf der Douyin-Plattform streben viele Benutzer danach, eine Level-Zertifizierung zu erhalten, und das Lichtzeichen der Stufe 10 zeigt den Einfluss und die Anerkennung des Benutzers auf Douyin. In diesem Artikel geht es um den Preis der Level-10-Lightboards von Douyin und um die Zeit, die es braucht, um dieses Level zu erreichen, um den Benutzern ein besseres Verständnis des Prozesses zu ermöglichen. 1. Wie viel kostet ein Douyin-Lichtschild der Stufe 10? Der Preis der 10-stufigen Lichtschilder von Douyin variiert je nach Marktschwankungen sowie Angebot und Nachfrage. Der allgemeine Preis liegt zwischen einigen tausend Yuan und zehntausend Yuan. In diesem Preis sind hauptsächlich die Kosten für das Lichtschild selbst und eventuelle Servicegebühren enthalten. Benutzer können Lichtschilder der Stufe 10 über die offiziellen Kanäle von Douyin oder über Drittanbieter-Serviceagenturen kaufen, sollten beim Kauf jedoch auf legale Kanäle achten, um falsche oder betrügerische Transaktionen zu vermeiden. 2. Wie viele Tage dauert die Erstellung eines Level-10-Fanschilds? Erreiche das Lichtzeichen der Stufe 10

Kann Linux die Systemzeit zurücksetzen? Kann Linux die Systemzeit zurücksetzen? Mar 13, 2023 am 10:50 AM

Linux kann die Systemzeit zurücksetzen: 1. Verwenden Sie den Befehl date, um die Uhrzeit zu überprüfen. 2. Verwenden Sie den Befehl „yum install ntp“, um ntp zu installieren „Befehl zum Implementieren der Netzwerkzeit. Einfach synchronisieren.

Wie lange dauert es, den Elden Ring zu räumen? Wie lange dauert es, den Elden Ring zu räumen? Mar 11, 2024 pm 12:50 PM

Spieler können die Haupthandlung des Spiels erleben und Spielerfolge sammeln, wenn sie in Elden's Circle spielen. Viele Spieler wissen nicht, wie lange es dauert, Elden's Circle zu bewältigen. Wie lange dauert es, den Elden Ring zu räumen? Antwort: 30 Stunden. 1. Diese 30-Stunden-Räumungszeit bezieht sich zwar nicht auf einen meisterhaften Speed-Pass, lässt aber auch viele Prozesse aus. 2. Wenn Sie ein besseres Spielerlebnis erhalten oder die komplette Handlung erleben möchten, müssen Sie auf jeden Fall mehr Zeit in die Dauer investieren. 3. Wenn die Spieler sie alle sammeln, dauert es etwa 100–120 Stunden. 4. Wenn Sie zum Bürsten von BOSS nur den Hauptfaden verwenden, dauert dies etwa 50–60 Stunden. 5. Wenn Sie alles erleben möchten: 150 Stunden Basiszeit.

Warum dauert die Kompilierung meines Go-Programms länger? Warum dauert die Kompilierung meines Go-Programms länger? Jun 09, 2023 pm 06:00 PM

In den letzten Jahren ist die Sprache Go für immer mehr Entwickler zur Wahl geworden. Im Vergleich zu anderen Programmiersprachen ist die Kompilierungsgeschwindigkeit der Go-Sprache jedoch nicht hoch genug. Viele Entwickler werden beim Kompilieren von Go-Programmen auf dieses Problem stoßen: Warum dauert das Kompilieren meines Go-Programms länger? In diesem Artikel wird dieses Problem unter verschiedenen Aspekten untersucht. Die Compiler-Architektur der Go-Sprache Die Compiler-Architektur der Go-Sprache verwendet ein dreistufiges Design: Front-End, Mittelschicht und Back-End. Das Front-End ist für die Übersetzung des Quellcodes in Zwischencode in der Go-Sprache verantwortlich, und die mittlere Ebene übernimmt die Aufgabe

So entfernen Sie Stunden, Minuten und Sekunden aus der Zeit in PHP So entfernen Sie Stunden, Minuten und Sekunden aus der Zeit in PHP Mar 13, 2023 am 11:20 AM

So entfernen Sie mit PHP Stunden, Minuten und Sekunden aus der Zeit: 1. Erstellen Sie eine PHP-Beispieldatei. 2. Verwenden Sie die Funktion strtotime, um Datum und Uhrzeit in einen Zeitstempel umzuwandeln. 3. Verwenden Sie die Datumsfunktion, um das Datum oder die Uhrzeit zu formatieren um die Stunden, Minuten und Sekunden zu entfernen.

Wie legt man den Zeitpunkt für die Veröffentlichung von Werken auf Xiaohongshu fest? Ist der Zeitpunkt für die Veröffentlichung der Arbeit korrekt? Wie legt man den Zeitpunkt für die Veröffentlichung von Werken auf Xiaohongshu fest? Ist der Zeitpunkt für die Veröffentlichung der Arbeit korrekt? Mar 24, 2024 pm 01:31 PM

Xiaohongshu, eine Plattform voller Leben und Wissensaustausch, ermöglicht es immer mehr Kreativen, ihre Meinung frei zu äußern. Um mehr Aufmerksamkeit und Likes auf Xiaohongshu zu bekommen, ist neben der Qualität der Inhalte auch der Zeitpunkt der Veröffentlichung der Werke entscheidend. Wie legt man also den Zeitpunkt fest, zu dem Xiaohongshu seine Werke veröffentlichen soll? 1. Wie legt man den Zeitpunkt für die Veröffentlichung von Werken auf Xiaohongshu fest? 1. Verstehen Sie die aktive Zeit der Benutzer. Zunächst muss die aktive Zeit der Xiaohongshu-Benutzer geklärt werden. Im Allgemeinen sind 20:00 bis 22:00 Uhr und Wochenendnachmittage die Zeiten, in denen die Benutzeraktivität hoch ist. Allerdings variiert dieser Zeitraum auch je nach Faktoren wie Zielgruppensegment und Geografie. Um die aktive Zeit der Nutzer besser zu erfassen, empfiehlt es sich daher, eine detailliertere Analyse der Verhaltensgewohnheiten verschiedener Gruppen durchzuführen. Indem wir das Leben der Benutzer verstehen

Ausführliche Erläuterung der Linux-Techniken zum Anzeigen der Dateizeit Ausführliche Erläuterung der Linux-Techniken zum Anzeigen der Dateizeit Feb 21, 2024 pm 01:15 PM

Ausführliche Erläuterung der Linux-Techniken zur Dateizeitanzeige In Linux-Systemen sind Dateizeitinformationen für die Dateiverwaltung und Nachverfolgung von Änderungen sehr wichtig. Das Linux-System zeichnet Dateiänderungsinformationen über drei Hauptzeitattribute auf, nämlich Zugriffszeit (atime), Änderungszeit (mtime) und Änderungszeit (ctime). In diesem Artikel wird detailliert beschrieben, wie diese Dateizeitinformationen angezeigt und verwaltet werden, und es werden spezifische Codebeispiele bereitgestellt. 1. Überprüfen Sie die Dateizeitinformationen, indem Sie den Befehl ls mit dem Parameter -l verwenden, um die Dateien aufzulisten.

So verwenden Sie die Zeit- und Datumsmodule in Python So verwenden Sie die Zeit- und Datumsmodule in Python Oct 16, 2023 am 08:11 AM

So verwenden Sie die Zeit- und Datumsmodule in Python. Einführung: In der Programmierung ist der Umgang mit Zeit und Datum eine sehr häufige Aufgabe. Python bietet leistungsstarke Zeit- und Datumsmodule, die Zeit- und Datumsoperationen einfacher und bequemer machen. In diesem Artikel werden die Zeit- und Datumsmodule in Python vorgestellt und spezifische Codebeispiele bereitgestellt, um den Lesern zu helfen, sie besser zu verstehen und anzuwenden. 1. Einführung in das Zeit- und Datumsmodul Das in Python integrierte Zeit- und Datumsmodul ist das Datum/Uhrzeit-Modul. Wir müssen dieses Modul zuerst vorstellen.