2013-11-22 15 views
11

http://en.wikipedia.org/wiki/H-indexalla ricerca di algoritmo per calcolare h-index veloce

questa pagina Wiki è una definizione di h-index

in fondo se dovessi avere una serie di [0 3 4 7 8 9 10], il mio h-index sarebbe 4 dato che ho 4 numeri più grandi di 4. Il mio h-index sarebbe stato 5 se avessi avuto 5 numeri più grandi di 5, e così via. Data una serie di numeri interi maggiori o uguali a 0, quali sono i modi per calcolare l'h-index in modo efficiente?

edit: la matrice non è necessariamente allineati

risposta

10

Ecco la mia realizzazione O (N) con presentazione, questo è semplice e velocissimo:

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

Buona soluzione! +1 – ElKamina

+2

Questo algoritmo è sbagliato, dovrebbe essere 'if (sum == i) return i;'. Ma anche allora è stato calcolato che ci sono i numeri 'i' che sono maggiori ** o uguali ** di' i' (cosa è corretto in base al link ma non a ciò che l'interrogante voleva sapere). Inoltre se non c'è corrispondenza (e quindi 'return') nel secondo ciclo' for' l'algoritmo restituisce '0', il che significa che ci sono numeri zero maggiori (o maggiori o uguali) di 0 che è contraddittorio per un (non vuoto) array contenente solo numeri maggiori o uguali a 0 (almeno se si controlla usando la relazione '> =' come è fatto ora). –

+1

Non ci sono commenti? Nessuna spiegazione? L'algoritmo potrebbe essere buono, ma non costringere i tuoi lettori a metterlo a tacere, almeno a condividere le idee principali. – timgeb

0

Questa è una soluzione che ho potuto pensare. non sono sicuro se è il migliore

Ordinare la matrice in ordine crescente. complessità nlog (n)

scorrere la matrice dall'indice 0 a n. complessità n

e per ogni iterazione, indice supponiamo è i

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

esempio,

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

Non è necessario ordinare (O (nlogn)). Vedi la mia soluzione che è O (n) – ElKamina

+0

__Sort__ in 'O (log N)'? Veramente? Devi essere geniale. –

+0

mi dispiace. :) che era un refuso –

1

Questo potrebbe essere fatto in O (n).

  1. Trova la mediana dell'array.
  2. se mediana> (n-1)/2 quindi il numero arriva prima della mediana. Trova iterativamente
  3. Se mediana < (n-1)/2, il numero viene dopo la mediana. Trovalo iterativamente.
  4. Se == mediana (n-1)/2, allora la mediana è la soluzione

Qui io parto dal presupposto che n è dispari. Cambia leggermente l'algoritmo per anche n (sostituisci (n + 1)/2 con n/2 supponendo che il rango di mediana sia n/2). Inoltre, trovare la mediana effettiva nel tempo O (n) è complicata. Utilizzare invece un buon pivot (come in quicksort).

Complessità: n + n/2 + n/4 ... = O (n)

+0

awsome = D, suppongo che linear sia il miglior risultato – cakester

+1

Questo è NLogN, poiché la ricerca della mediana dovrebbe essere eseguita in tutti gli array. –

+0

E i casi in cui la risposta non è all'interno dell'array? Esempio [0 0 0 9 9 9] –

-1

Non ero soddisfatto della mia precedente implementazione, quindi l'ho sostituito con una soluzione più veloce scritta in Java.

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; 
} 
Problemi correlati