2016-05-26 58 views
9

stavo cercando di risolvere questo problema: https://leetcode.com/problems/longest-substring-without-repeating-characters/Codice in for-loop vs if-else

Il seguente codice superato tutti i test in 44 ms.

for (int i = 0; i < s.length(); i++){ 
     if (!mp.containsKey(s.charAt(i))){ 
      mp.put(s.charAt(i), i); 
      //max = Math.max(max, i-first+1); 
     } 
     else { 
      if (mp.get(s.charAt(i))+1>=first){ 
       first = mp.get(s.charAt(i))+1; 
      } 
      mp.put(s.charAt(i), i); 
      //max = Math.max(max, i-first+1); 
     } 
     max = Math.max(max, i-first+1); 
    } 

Ma il seguente codice superato tutti i test in soli 20 ms.

for (int i = 0; i < s.length(); i++){ 
     if (!mp.containsKey(s.charAt(i))){ 
      mp.put(s.charAt(i), i); 
      max = Math.max(max, i-first+1); 
     } 
     else { 
      if (mp.get(s.charAt(i))+1>=first){ 
       first = mp.get(s.charAt(i))+1; 
      } 
      mp.put(s.charAt(i), i); 
      max = Math.max(max, i-first+1); 
     } 
    } 

Perché c'è una differenza così significativa? Il valore massimo viene modificato una sola volta in entrambi i campioni, ma cambiarlo nelle istruzioni if-else è molto più efficiente rispetto a cambiarlo alla fine del ciclo for. Questa è un'eccezione o dovremmo seguire questo standard ogni volta che programmiamo?

+0

È difficile prevedere esattamente quali sarebbero gli effetti di tale trasformazione sul codice macchina. Forse ha finito per organizzare i suoi salti in modo diverso? Puoi scaricare il codice assembly? – harold

+1

è questa l'ora dal sito web in cui hai inserito il codice? Forse è un ritardo del loro interprete? Dovresti controllare questo su un sistema locale con un vm locale e un framework delle prestazioni – Supahupe

+0

È altamente improbabile che i due programmi si comportino diversamente ... Quello che osservi è probabilmente correlato a quanto era occupato il server quando hai inviato il tuo codice. Dovresti testarlo in un ambiente controllato. – assylias

risposta

1

sulla semplificazione (non anticipata sull'ottimizzazione, vedere max!) Si ottiene

for (int i = 0; i < s.length(); i++) { 
    char ch = s.charAt(i); 
    Integer n = mp.get(ch): 
    if (n != null) { 
     first = Math.max(first, n + 1); 
    } 
    mp.put(ch, i); 
    max = Math.max(max, i - first + 1); 
} 

Nota la doppia put di valore i nella versione originale. Se il primo Math.max viene sostituito con un if, il codice potrebbe essere più veloce.

È difficile fare una dichiarazione w.r.t. per accelerare qui per le due versioni originali, forse il compilatore hotspot ha visto la ridondanza. O qualsiasi altra cosa

Sarebbe bello vedere una versione java 8, utilizzando mp.putIfAbsent o simili, ma potrebbe rallentarlo.

+0

@Hulk grazie, 'prima' (massimizzando con se stessi) dovrebbe sono stato. Corretto. Difficile da leggere. –