it-swarm.com.de

Was ist der beste Weg, um den Minimal- oder Maximalwert aus einem Array von Zahlen zu erhalten?

Nehmen wir an, ich habe ein Zahlenfeld: [2,3,3,4,2,2,5,6,7,2]

Was ist der beste Weg, um den minimalen oder maximalen Wert in diesem Array zu finden?

Um das Maximum zu erhalten, durchläuft ich das Array und setze eine Variable auf den Wert zurück, wenn dieser größer als der vorhandene Wert ist:

var myArray:Array /* of Number */ = [2,3,3,4,2,2,5,6,7,2];

var maxValue:Number = 0;

for each (var num:Number in myArray)
{
    if (num > maxValue)
        maxValue = num;
}

Dies scheint einfach nicht der beste Weg zu sein (ich versuche, Loops möglichst zu vermeiden).

33
Eric Belair

Die theoretischen Antworten aller anderen sind ordentlich, aber seien wir pragmatisch. ActionScript bietet die Tools, die Sie benötigen, damit Sie in diesem Fall nicht einmal eine Schleife schreiben müssen!

Beachten Sie zunächst, dass Math.min() und Math.max() eine beliebige Anzahl von Argumenten aufnehmen können. Außerdem ist es wichtig, die apply()-Methode zu verstehen, die für Function-Objekte verfügbar ist. Es erlaubt Ihnen, Argumente mit einer Array an die Funktion zu übergeben. Lassen Sie uns beide nutzen:

var myArray:Array = [2,3,3,4,2,2,5,6,7,2];
var maxValue:Number = Math.max.apply(null, myArray);
var minValue:Number = Math.min.apply(null, myArray);

Das Beste daran: Die "Schleife" wird tatsächlich mit nativem Code (in Flash Player) ausgeführt. Sie ist also schneller als die Suche nach dem Mindest- oder Höchstwert mithilfe einer reinen ActionScript-Schleife.

81
joshtynjala

Es gibt keine zuverlässige Methode, um das Minimum/Maximum zu ermitteln, ohne jeden Wert zu testen. Sie möchten keine Sortierung oder ähnliches versuchen. Das Durchlaufen des Arrays ist O (n). Dies ist besser als jeder Sortieralgorithmus im allgemeinen Fall.

30
Adam Bellaire

Ob

  1. Das Array ist nicht sortiert
  2. Das Finden von min und max erfolgt gleichzeitig

Dann gibt es einen Algorithmus, der das Minimum und Maximum in 3n/2 Vergleichen ermittelt. Was man tun muss, ist die paarweise Verarbeitung der Elemente des Arrays. Der größere des Paares sollte mit dem aktuellen max und der kleinere des Paares mit dem aktuellen min verglichen werden. Es ist auch besondere Vorsicht geboten, wenn das Array eine ungerade Anzahl von Elementen enthält.

In C++ - Code (etwas von Mehrdad ausleihen).

struct MinMax{
   int Min,Max;
}

MinMax FindMinMax(int[] array, int start, int end) {
   MinMax  min_max;
   int index;
   int n = end - start + 1;//n: the number of elements to be sorted, assuming n>0
   if ( n%2 != 0 ){// if n is odd

     min_max.Min = array[start];
     min_max.Max = array[start];

     index = start + 1;
   }
   else{// n is even
     if ( array[start] < array[start+1] ){
       min_max.Min = array[start];
       min_max.Max = array[start+1];
     }
     else{
       min_max.Min = array[start+1];
       min_max.Max = array[start];
     }
     index = start + 2;
   }

   int big, small;
   for ( int i = index; i < n-1; i = i+2 ){
      if ( array[i] < array[i+1] ){ //one comparison
        small = array[i];
        big = array[i+1];
      }
      else{
        small = array[i+1];
        big = array[i];
      }
      if ( min_max.Min > small ){ //one comparison
        min_max.Min = small;
      }
      if ( min_max.Max < big ){ //one comparison
        min_max.Max = big;
      }
   }

   return min_max;
}

Es ist sehr leicht zu sehen, dass die Anzahl der Vergleiche 3n/2 beträgt. Die Schleife läuft n/2 mal und in jeder Iteration werden 3 Vergleiche durchgeführt. Dies ist wahrscheinlich das Optimum, das man erreichen kann. Zu diesem Zeitpunkt kann ich nicht auf eine bestimmte Quelle verweisen. (Aber ich glaube, ich habe irgendwo einen Beweis dafür gesehen.)

Die rekursive Lösung von Mehrdad oben erreicht wahrscheinlich auch diese minimale Anzahl von Vergleichen (die letzte Zeile muss geändert werden). Bei der gleichen Anzahl von Vergleichen wird eine iterative Lösung jedoch immer eine rekursive Lösung schlagen, da der Funktionsaufruf einen Overhead verursacht. Wenn Sie jedoch nur darauf achten, min und max von ein paar Zahlen zu finden (wie bei Eric Belair), wird niemand einen Unterschied im heutigen Computer mit den oben genannten Ansätzen bemerken. Bei einem großen Array kann der Unterschied erheblich sein.

Obwohl diese Lösung und die von Matthew Brubaker gegebene Lösung O(n) Komplexität aufweisen, sollte man in der Praxis die verborgenen Konstanten sorgfältig einschätzen. Die Anzahl der Vergleiche in seiner Lösung beträgt 2n. Die mit der Lösung gewonnene Beschleunigung mit 3n/2-Vergleichen im Vergleich zu 2n-Vergleichen wäre spürbar.

27
Rayhan

Wenn das Array nicht sortiert ist, ist es das Beste, das Sie erhalten. Wenn es sortiert ist, nimm einfach das erste und das letzte Element.

Wenn es nicht sortiert ist, ist es natürlich weniger effizient, zuerst zu sortieren und das Erste und Letzte zu packen, als nur einmal durchlaufen zu müssen. Selbst die besten Sortieralgorithmen müssen jedes Element mehr als einmal betrachten (ein Durchschnitt von O (log N) -Zeiten für jedes Element. Das ist O (N * Log N) insgesamt. Ein einfacher Scan ist nur O (N).

Wenn Sie einen schnellen Zugriff auf das größte Element in einer Datenstruktur wünschen, werfen Sie einen Blick auf Heaps, um die Objekte auf eine effiziente Art und Weise zu halten.

19
Eclipse

Sie müssen das Array durchlaufen, keine andere Möglichkeit, alle Elemente zu überprüfen. Nur eine Korrektur für den Code - wenn alle Elemente negativ sind, wird maxValue am Ende 0 sein. Sie sollten es mit dem minimal möglichen Wert für Ganzzahl initialisieren. 
Wenn Sie das Array viele Male durchsuchen möchten, ist es eine gute Idee, es zuerst zu sortieren, da die Suche schneller ist (binäre Suche) und Minimum- und Maximumelemente nur das Erste und das Letzte sind.

12
Rumen Georgiev

Hängt davon ab, was Sie "am besten" nennen. Aus theoretischer Sicht können Sie das Problem in einer deterministischen Turingmaschine nicht in weniger als O(n) lösen.

Der naive Algorithmus ist zu loop und update min, max. Eine rekursive Lösung erfordert jedoch weniger Vergleiche als der naive Algorithmus, wenn Sie min, max gleichzeitig erhalten möchten (aufgrund des Funktionsaufrufs ist dies nicht unbedingt schneller).

struct MinMax{
   public int Min,Max;
}

MinMax FindMinMax(int[] array, int start, int end) {
   if (start == end)
      return new MinMax { Min = array[start], Max = array[start] };

   if (start == end - 1)
      return new MinMax { Min = Math.Min(array[start], array[end]), Max = Math.Max(array[start], array[end]) } ;

   MinMax res1 = FindMinMax(array, start, (start + end)/2);
   MinMax res2 = FindMinMax(array, (start+end)/2+1, end);
   return new MinMax { Min = Math.Min(res1.Min, res2.Min), Max = Math.Max(res1.Max, res2.Max) } ;
}

Die einfachste Lösung wäre, das erste und letzte Objekt zu sortieren und zu erhalten, obwohl es offensichtlich nicht das schnellste ist;)

Die beste Lösung, was die Leistung angeht, um das Minimum zu finden oder Maximum ist der naive Algorithmus, den Sie geschrieben haben (mit einer einzigen Schleife). 

4
Mehrdad Afshari

Math.max () ist eigentlich ein nach AVM2-Opcodes kompilierter AS3-Code und daher nicht mehr "native" als jeder andere AS3-Code. Folglich ist es nicht notwendigerweise die schnellste Implementierung.

In Anbetracht dessen, dass es mit dem Array-Typ funktioniert, ist es langsamer als der sorgfältig geschriebene Code, der Vector verwendet:

Ich habe einen schnellen Benchmark-Vergleich verschiedener naiver Vektor- und Array-Implementierungen von Math.max durchgeführt, wobei gskinners PerformanceTest verwendet wurde (Vektor und Array wurden mit identischen Zufallszahlen gefüllt) .. Die schnellste Vector-Implementierung schien mehr als dreimal schneller als Math zu sein. max mit dem letzten AIR SDK/Release-Player (Flash Player WIN 14,0,0,122 RELEASE, zusammengestellt mit AIR SDK 14):

durchschnitt 3,5 ms für 1.000.000 Werte im Vergleich zu Math.max () Durchschnitt von 11ms:

function max(values:Vector.<Number>):Number
{
    var max:Number = Number.MIN_VALUE;
    var length:uint = values.length;
    for (var i:uint = 0; i < length ; ++i)
        if (values[i] > max)
            max = values[i];
    return max;
}

Fazit: Wenn Sie von der Leistung betroffen sind, sollten Sie Vector over Array überall dort einsetzen, wo Sie dies überhaupt können, und sollten sich nicht immer auf Standardimplementierungen verlassen, insbesondere wenn sie die Verwendung von Array erzwingen

PS: Dieselbe Implementierung mit einer for Each () - Schleife ist 12x langsamer ...!

3
jauboux

Wenn Sie das Array einmal erstellen und das Maximum nur einmal ermitteln möchten, ist Iteration das Beste, was Sie tun können.

Wenn Sie das Array ändern möchten und gelegentlich das maximale Element erfahren möchten, sollten Sie eine Priority Queue verwenden. Eine der besten Datenstrukturen dafür ist ein Fibonacci-Heap . Wenn dies zu kompliziert ist, verwenden Sie einen Binary-Heap , der langsamer aber dennoch gut ist.

Um Minimum und Maximum zu ermitteln, erstellen Sie einfach zwei Haufen und ändern Sie das Vorzeichen der Zahlen in einem von ihnen.

2
martinus

Dies hängt von den Anforderungen der realen Anwendung ab.

Wenn Ihre Frage nur hypothetisch ist, wurden die Grundlagen bereits erläutert. Es ist ein typisches Such- oder Sortierproblem. Es wurde bereits erwähnt, dass Sie algorithmisch nicht besser als O(n) für diesen Fall erreichen werden.

Wenn Sie jedoch die praktische Anwendung betrachten, werden die Dinge interessanter. Sie müssen dann prüfen, wie groß das Array ist und welche Prozesse beim Hinzufügen und Entfernen aus dem Datensatz erforderlich sind. In diesen Fällen kann es am besten sein, den rechnerischen "Treffer" zum Einfügungs-/Entfernungszeitpunkt durch fliegendes Sortieren zu erhalten. Einfügungen in ein vorsortiertes Array sind nicht so teuer.

Die schnellste Abfrageantwort auf die Min Max-Anforderung wird immer von einem sortierten Array stammen, da Sie, wie andere bereits erwähnt haben, einfach das erste oder letzte Element verwenden, was Ihnen O(1) Kosten verursacht.

Weitere technische Informationen zu den Rechenaufwand und die Big-O-Notation finden Sie im Wikipedia-Artikel here .

Nick.

2
Nick

Bitte beachten Sie, dass das Sortieren des Arrays nur schneller ist, als bis zu einer bestimmten Größe des Arrays. Wenn Ihr Array klein ist (und es wird jederzeit so sein), ist Ihre Lösung vollkommen in Ordnung. Wenn es jedoch zu groß wird, sollten Sie eine Bedingung verwenden, um den Sortieransatz zu verwenden, wenn das Array klein ist und die normale Iteration, wenn es zu groß ist

1
Javier

Es gibt verschiedene Möglichkeiten, dies zu erreichen.

  1. Rohe Gewalt. Lineare Suche für min und max getrennt. (2N Vergleiche und 2N Schritte) 
  2. Linear iterieren und jede Zahl auf min und max überprüfen. (2N Vergleiche) 
  3. Benutze Divide und erobere. (Zwischen 2N und 3N/2 Vergleichen) 
  4. Vergleichen Sie die unten erläuterten Paare: (3N/2-Vergleiche)

Wie kann man mit minimalen Vergleichen Max und Min in einem Array finden?


Wenn Sie hinsichtlich Geschwindigkeit, Laufzeit und Anzahl der Vergleiche wirklich paranoid sind, finden Sie weitere Informationen unter http://www.geeksforgeeks.org/maximum-and-minimum-in-an-array/

0
Shogo Warrior

Algorithmus MaxMin (erster, letzter, max, min)

// Dieser Algorithmus speichert das höchste und das niedrigste Element

// Werte des globalen Arrays A in den globalen Variablen max und min

// tmax und tmin sind temporäre globale Variablen 

{
if (first==last) //Sub-array contains single element
 {
    max=A[first];
    min=A[first];
 }
 else if(first+1==last) //Sub-array contains two elements
  {
     if(A[first]<A[Last])
      {
      max=a[last];  //Second element is largest
      min=a[first]; //First element is smallest
      }
   else
   {
     max=a[first]; //First element is Largest 
     min=a[last];  //Second element is smallest
   }
}
else
 //sub-array contains more than two elements
{
 //Hence partition the sub-array into smaller sub-array 
 mid=(first+last)/2;
 //Recursively solve the sub-array
 MaxMin(first,mid,max,min);
 MaxMin(mid+1,last,tmax,tmin);
 if(max<tmax)
  {
     max=tmax;
  }
    if(min>tmin)
  {
   min=tmin;
  }
 }
}
0

Max-Werte aus einem Array finden Sehen wir uns an, wie Sie mit einer einzigen Funktion Min-, Max-Werte erhalten

public void findMaxValue(){
   int[] my_array = {1,2,,6,5,8,3,9,0,23};
   int max = my_array[0];
   for(int i=1; i<my_array.length; i++)
   {
      if(my_array[i] > max)
         max = my_array[i];
   }
   return max; 
}

dasselbe kann man für einen minimalen Wert tun

Erstaunt hat hier niemand Parallelität erwähnt.

Wenn Sie wirklich ein großes Array haben, können Sie parallel-for für Unterbereiche verwenden. Am Ende müssen Sie alle Unterbereiche miteinander vergleichen. Parallelität bringt jedoch auch einige Nachteile mit sich, so dass dies nicht für kleine Arrays optimiert wird . Wenn Sie jedoch große Datensätze erhalten haben, macht dies Sinn und Sie erhalten eine Zeiteinteilung, die sich der Anzahl der Threads nähert, die den Test durchführen.

0
user3800527

Unten ist Lösung mit o (n): -

public static void findMaxAndMinValue(int A[]){
    int min =0, max = 0;
    if(A[0] > A[1] ){
        min = A[1];
        max = A[0];
    }else{
        max = A[1];
        min = A[0];
    }
    for(int i = 2;i<A.length ;i++){
        if(A[i] > max){
            max = A[i];
        }
        if(min > A[i]){
            min = A[i];
        }
    }
    System.out.println("Maxinum Value is  "+min+" & Minimum Value is  "+max);
}
0
Ajay

Kürzester Weg: 

Math.min.apply (null, Array); // Dies gibt den Mindestwert aus dem Array zurück
Math.max.apply (null, Array); // Dies gibt den maximalen Wert aus dem Array zurück 

auf andere Weise den minimalen und maximalen Wert von einem Array erhalten

 function maxVal(givenArray):Number
    {
    var max = givenArray[0];
    for (var ma:int = 0; ma<givenArray.length; ma++)
    {
    if (givenArray[ma] > max)
    {
    max = givenArray[ma];
    }
    }
    return max;
    }

    function minVal(givenArray):Number
    {
    var min = givenArray[0];
    for (var mi:int = 0; mi<givenArray.length; mi++)
    {
    if (givenArray[mi] < min)
    {
    min = givenArray[mi];
    }
    }
    return min;
    }

Wie Sie sehen, ist der Code in beiden Funktionen sehr ähnlich. Die Funktion legt eine Variable fest (max (oder min)) und läuft dann mit einer Schleife durch das Array, wobei jedes nächste Element überprüft wird. Wenn das nächste Element höher als der Strom ist, setzen Sie es auf max (oder min). Geben Sie am Ende die Nummer zurück.

0

Wenn Sie min und max gleichzeitig suchen möchten, können Sie die Schleife wie folgt ändern:

int min = int.maxValue;
int max = int.minValue;

foreach num in someArray {
  if(num < min)
    min = num;
  if(num > max)
    max = num;
}

Dies sollte das Timing O(n) erreichen.

0