2012-04-14 9 views
2

Ich versuche, einen Algorithmus zu schreiben, um wahr zurückzugeben, wenn ein Majoritätselement in einem Array existiert und andernfalls falsch. edit: ich kann nur sagen, ob zwei Elemente gleich sind. was bedeutet, dass ich < oder>, only = nicht verwenden kann. edit: Die Lösung sollte in einer Divide-and-Conquer-Methode sein. seine Laufzeit über nlogn gehen shouldnt, und ich schrieb etwas in Java, aber ich bin nicht sicher, ob es richtig ist, und wie die Laufzeit zu berechnen .. hier ist das, was ich habe:Algorithmen | Majoritätselement

public static boolean MajorityBoolean(int[] arr) { 
    int c; 
    int n = arr.length; 
    for (int i = 0; i < n; i = i + 2) { 
     System.out.println("*"); 
     if ((arr[i] == arr[(i + 1)%n]) || ((arr[i] == arr[(i - 1+n)%n]))) { 
      c = 0; 
      for (int j = 0; j < n; j = j + 1) 
       if (arr[j] == arr[i]) 
        c = c + 1; 
      if (c > n/2) 
       return true; 
     } 
    } 
    return false; 
} 
+0

I a hinzugefügt erscheint Hausaufgaben-Tag, da es so zu sein scheint. Wenn ich mich irre, korrigiere mich bitte. – amit

+0

mögliches Duplikat von [Hauptelement im Array suchen] (http://stackoverflow.com/questions/4325200/find-majority-element-in-array) – erickson

+0

Speziell [this] (http://stackoverflow.com/a/9487018/3474) ist die beste Lösung für die doppelte Frage. – erickson

Antwort

5

Die Laufzeit des beschriebenen Algorithmus ist O(n^2). Die äußere Schleife wird n/2 mal ausgeführt, somit wird der innere Zähler jn/2 mal zurückgesetzt, und somit wird die innere Schleife insgesamt O(n^2) mal ausgeführt.

Ich bin nicht sicher, ich verfolge die Logik hinter Ihrer Idee, aber hier sind zwei Ansätze, wie ich es umsetzen würde [in hohem Niveau Pseudo-Code]:

(1) erstellen histogram aus der Daten:

  • erstellen Map<Integer,Integer> [der Schlüssel ist, das Element und der Wert ist die Anzahl der Vorkommen]
  • iterieren das Array und für jedes Element zählen, wie oft es
  • iterieren des Histogramms angezeigt wird, und Finde heraus, ob es ein einzigartiges Maximum gibt.
  • Wenn es gibt - Rückgabe wahr, sonst Rückgabe false.

Dieser Ansatz ist durchschnittlich O(n), wenn Sie ein HashMap als die Karte verwenden.

(2) zu sortieren und zu max Vorkommen finden:

  • sortieren das Array - als Ergebnis, alle gleich Elemente zueinander benachbart sind. Sie können Arrays.sort(array) zum Sortieren verwenden.
  • Zählen Sie, wie oft jedes Element angezeigt wird [ähnlich der Histogramm-Idee], und finden Sie heraus, ob es ein eindeutiges Maximum gibt. Sie müssen nicht wirklich die Daten für alle Elemente pflegen, es ist genug für die Top-2 zu halten, und am Ende zu sehen, ob sie identisch sind.

Diese Lösung ist O(nlogn) Durchschnitt + worst case [tatsächlich je nach Art - merge sor t Sie O(nlogn) schlimmsten Fall gibt, während quick-sort gibt Ihnen O(n^2) schlimmsten Fall, und beide sind O(nlogn) im Durchschnitt Fall].

EDIT:

ich das Problem bei der Hand falsch verstanden, ich dachte, Sie schauen, ob es eine eindeutige Maximum ist. Diese 2 Lösungen passen immer noch für das Problem, Sie müssen nur den letzten Schritt jedes [ändern, um zu überprüfen, ob das am häufigsten vorkommende Element mehr als die Hälfte der Zeiten erscheint, was wiederum in O(n)] ziemlich einfach und machbar ist.

Es gibt auch eine andere Lösung: Verwenden Sie selection algorithm, um den Median zu finden, und nachdem Sie ihn gefunden haben, prüfen Sie, ob es ein Majoritätselement ist, und geben Sie es zurück. Da der Auswahlalgorithmus eine Lösung ist, die auf Teilen und Siegen basiert, denke ich, dass sie zu Ihren Bedürfnissen passt.

+0

zuerst, danke für Sie Hilfe! Zweitens war meine Idee, dass in jedem Array, das ein Majority-Element hat, zwei identische Zahlen hintereinander sein müssen (in Anbetracht der Tatsache, dass das Array eine Art Kreis ist, so dass das letzte Element nahe bei dem ersten ist). Ist das eine gute Idee? Übrigens musste ich den Algorithmus offensichtlich in einer Divide-n-Conquer-Methode schreiben, also ist meine nicht gut (auch seine Laufzeit ist O (n²), was mehr ist als) (nlogn)). – shachar0n

+0

@ shachar0n: (1) Ich folge immer noch nicht der Logik, warum ist das Array kreisförmig? : \. (2) Ich habe die Frage missverstanden, ich dachte, du würdest schauen, ob es ein einzigartiges Maximum gibt. Diese zwei Lösungen passen immer noch zum Problem, mit einer leichten Modifikation im letzten Schritt jeder Lösung. (3) Die von Ihnen beschriebene Frage kann mit [Auswahlalgorithmus] (http://en.wikipedia.org/wiki/Selection_algorithm) gelöst werden. Finde den Median - und schau dann, ob es das Majoritätselement ist. Der Auswahlalgorithmus ist tatsächlich eine Lösung zum Teilen und Erobern. – amit

+0

(1) Was war, wenn ein Array ein Majority-Element hat, muss es zwei close-Elemente haben, die gleich sind. Wenn das Array so ist: 1010101, dann sind das letzte und das erste Element gleich - und das meine ich, indem ich das Array wie einen Kreis behandle (mit modulu%). (2) (3) Ich habe vergessen, eine weitere Einschränkung zu erwähnen: Ich kann nur wissen, ob zwei Elemente gleich sind, aber ich kann nicht sagen, ob einer größer oder kleiner ist als der andere, dh ich kann nur = verwenden und nicht verwenden :><. – shachar0n

0

folgt ein O (n) Lösung Find Majority Element

+0

Dies ist ein Hinweis auf eine gute Lösung, aber Sie sollten abstimmen, um doppelte Fragen zu schließen, wenn Sie können, oder einfach einen Kommentar zu der Frage abgeben, wenn Sie das nicht können. – erickson

1

Eine Mehrheit Element in einem Array A [] der Größe N ist ein Element, das mehr als n/2 Mal

public static boolean find(int[] arr, int size) { 
int count = 0, i, mElement; 
for (i = 0; i < size; i++) { 
    if (count == 0) 
     mElement = arr[i]; 
    if (arr[i] == mElement) 
     count++; 
    else 
     count--; 
} 
count = 0; 
for (i = 0; i < size; i++) 
    if (arr[i] == mElement) 
     count++; 
if (count > size/2) 
    return true; 
return false; 
}