2013-11-22 9 views
11

http://en.wikipedia.org/wiki/H-indexSuche-Algorithmus h-Index schnell

Diese Wikiseite ist eine Definition von h-Index

grundsätzlich zu berechnen, wenn ich einen Arrays haben bin [0 3 4 7 8 9 10], Mein h-Index wäre 4, da ich 4 Zahlen größer als 4 hätte. Mein h-Index wäre 5 gewesen, wenn ich 5 Zahlen größer als 5 hätte, und usw. Bei einem Array von ganzen Zahlen größer oder gleich 0, Wie kann der h-index effizient berechnet werden?

edit: das Array nicht notwendigerweise sortiert

Antwort

10

Hier ist meine Erkenntnis O (N) mit Einreichungs, ist dies einfach und blitzschnelle:

private static int GetHIndex(int[] m) 
{ 
    int[] s = new int[m.Length + 1]; 
    for (int i = 0; i < m.Length; i++) s[Math.Min(m.Length, m[i])]++; 

    int sum = 0; 
    for (int i = s.Length - 1; i >= 0; i--) 
    { 
     sum += s[i]; 
     if (sum >= i) 
      return i; 
    } 

    return 0; 
} 
+0

Gute Lösung! +1 – ElKamina

+2

Dieser Algorithmus ist falsch, es sollte sein 'if (sum == i) return i; '. Aber selbst dann berechnete es, dass es "i" -Nummern gibt, die größer ** oder gleich ** sind als "i" (was gemäß dem Link korrekt ist, aber nicht zu dem, was der Fragesteller wissen wollte). Wenn in der zweiten 'for'-Schleife keine Übereinstimmung (und daher kein' return') gefunden wird, gibt der Algorithmus '0' zurück, was bedeutet, dass es 0 (größer oder gleich) 0 gibt, die für (nicht-leere) widersprüchlich sind) Array, das nur Zahlen enthält, die größer oder gleich 0 sind (zumindest wenn Sie die Beziehung '>' 'wie bisher) verwenden. –

+1

Keine Kommentare? Keine Erklärung? Der Algorithmus mag gut sein, aber zwinge deine Leser nicht dazu, sie zu durchdenken, teile zumindest die Kernidee (n). – timgeb

0

Dies ist eine Lösung, die ich denken konnte. nicht sicher, ob es das Beste ist.

Sortieren Sie das Array in aufsteigender Reihenfolge. Komplexität nlog (n)

Iterieren durch die Anordnung aus dem Index 0 bis n. Komplexität der n

und für jede Iteration wird suppose Index i

if (arr[i] == (arr.length - (i+1)) 
    return arr[i] 

z.B.

arr =[ 0 3 4 7 8 9 10 ] 
arr[2] = 4 
i = 2 
arr.length = 7 
4 = (7- (2+1)) 
+0

Keine Sortierung (O (nlogn)). Siehe meine Lösung, die ist O (n) – ElKamina

+0

__Sort__ in 'O (log N)'? "Ja wirklich?" Du musst Genie sein. –

+0

tut mir leid. :) Das war ein Tippfehler –

1

Dies könnte in O (n) Zeit durchgeführt werden.

  1. Suchen Sie den Median des Arrays.
  2. Wenn der Median> (n-1)/2 ist, dann kommt die Zahl vor dem Median. Finden Sie es iterativ
  3. Wenn Median < (n-1)/2 dann die Zahl nach dem Median kommt. Finde es iterativ.
  4. Wenn Median == (n-1)/2 ist, dann ist der Median der Lösung

Hier ungerade dass n Ich gehe davon aus. Ändern Sie den Algorithmus leicht für gerade n (ersetzen Sie (n + 1)/2 durch n/2, wenn der Rang des Medianwerts n/2 ist). Außerdem ist es schwierig, den tatsächlichen Median in O (n) -Zeit zu finden. Verwenden Sie stattdessen einen guten Pivot (wie in Quicksort).

Komplexität: n + n/2 + n/4 ... = O (n)

+0

awsome = D, Ich denke, linear ist das beste Ergebnis – cakester

+1

Dies ist NLogN, als Suche von Median sollte in allen Array erfolgen. –

+0

Was ist mit Fällen, wenn die Antwort nicht im Array ist? Beispiel [0 0 0 9 9 9] –

-1

Ich war nicht glücklich mit meiner vorherigen Implementierung, also ersetzte ich es durch eine schnellere Lösung in Java geschrieben.

public int hIndex(int[] citations) { 
    if(citations == null || citations.length == 0) 
    { 
     return 0; 
    } 

    Arrays.sort(citations); 

    int hIndex = 0; 

    for(int i=0;i<citations.length;i++) 
    { 
     int hNew; 

     if(citations[i]<citations.length-i) 
     { 
      hNew = citations[i]; 

      if(hNew>hIndex) 
      { 
       hIndex = hNew; 
      } 
     } 
     else if(citations[i]>=citations.length-i) 
     { 
      hNew = citations.length-i; 

      if(hNew>hIndex) 
      { 
       hIndex = hNew; 
      } 

      break; 
     } 
    } 

    return hIndex; 
}