2015-07-15 16 views
11

Mi sto preparando per una domanda di intervista. Una delle domande è di annullare una frase. Come "è un giorno fantastico" per "giorno fantastico a suo". Dopo questo, hanno chiesto se c'è una duplicazione, puoi rimuovere la duplicazione come "Io sono buono, è buono" a "buono è, sono io" .Inversione e rimozione di duplicati in una frase

per l'inversione della frase che ho scritto metodo

public static string reversesentence(string one) 
{ 
    StringBuilder builder = new StringBuilder(); 

    string[] split = one.Split(' '); 
    for (int i = split.Length-1; i >= 0; i--) 
    { 

     builder.Append(split[i]); 
     builder.Append(" "); 
    } 
    return builder.ToString(); 

} 

seguente ma io non sono sempre le idee sulla rimozione di duplication.Can io ottenga un certo aiuto qui.

+0

è possibile utilizzare le manipolazioni di stringhe – dada

+1

Bene, un approccio ingenuo potrebbe essere quello di verificare se 'split [i]' si è verificato o meno tra 'split [i + 1]' a 'split [split.Length -1]' I indovina! – user007

+1

Anche l'uso di un hash di qualche tipo è utile. Usa la parola come chiave e assegna il valore 1. La stessa parola che appare più di una volta assegnerà semplicemente 1 a un valore esistente. Non so come farlo in C#, ma lo faccio sempre in Perl. – Anthony

risposta

9

Questo funziona:

public static string reversesentence(string one) 
{ 
    Regex reg = new Regex("\\w+"); 
    bool isFirst = true; 
    var usedWords = new HashSet<String>(StringComparer.InvariantCultureIgnoreCase); 
    return String.Join("", one.Split(' ').Reverse().Select((w => { 
     var trimmedWord = reg.Match(w).Value; 
     if (trimmedWord != null) { 
      var wasFirst = isFirst; 
      isFirst = false; 

      if (usedWords.Contains(trimmedWord)) //Is it duplicate? 
       return w.Replace(trimmedWord, ""); //Remove the duplicate phrase but keep punctuation 

      usedWords.Add(trimmedWord); 

      if (!wasFirst) //If it's the first word, don't add a leading space 
       return " " + w; 
      return w; 
     } 
     return null; 
    }))); 
} 

In sostanza, noi decidere se è distinto basato sulla parola, senza punteggiatura. Se esiste già, basta restituire la punteggiatura. Se non esiste, stampa l'intera parola inclusa la punteggiatura.

punteggiatura rimuove anche lo spazio nel tuo esempio, che è il motivo per cui non possiamo fare String.Join(" ", ...) (altrimenti il ​​risultato sarebbe good he Is , am I invece di good he Is, am I

prova:

reversesentence("I am good, Is he good").Dump();

Risultato:

good he Is, am I

+1

'" (\\ b)? \\ w + (\\ b)? "' Il controllo del contorno opzionale sembra pescoso. È come se non lo controllassi affatto. – nhahtdh

+0

@nhahtdh Le parole non * necessitano * di limiti per essere definiti come parole, ma * possono * avere confini. Ad esempio, 'A B' - A ha un limite alla fine, B non ha confini. 'A' non ha confini,' A' ha un limite all'inizio, ma non alla fine. Lo controlla sicuramente, ma non lo richiede. – Rob

+0

@nhahtdh Nevermind, non sto pensando dritto oggi .. hai ragione - in tutti i casi non ha bisogno di prendere il confine. Aggiornerò il codice – Rob

3

Gli altri punti di risposta ad usare astrazioni ma gli intervistatori di solito vogliono vedere l'implementazione

F o l'inversione, il solito trucco è invertire prima la frase e poi invertire ogni parola mentre viaggi da sinistra a destra. Uno spazio ti dirà che hai raggiunto la fine di una parola. (Vedi le interviste di programmazione esposte per una soluzione a questo o semplicemente google.Questa era una domanda di intervista molto popolare). Il tuo approccio funziona ma è disapprovato perché stai usando uno spazio extra (O (n)).

Per la rimozione dei duplicati, se si lavora solo con ASCII, è possibile fare quanto segue:

bool[] seenChars = new bool[128]; 
    var sb = new StringBuilder(); 

    foreach(char c in stringOne) 
    { 
     if(!seenChars[c]){ 
      seenChars[c] = true; 
      sb.Append(c); 
     } 
    } 

    return sb.ToString(); 

L'idea è quella di utilizzare il valore del char come indice nella matrice di dirvi se hai visto questo personaggio prima o no. Con questo approccio, utilizzerai lo spazio O (1)!

Modifica: Se si desidera deduplicare le parole, probabilmente si desidera utilizzare un hashset e ignorarlo aggiungendolo se esiste già.

+0

Questo rimuove i caratteri duplicati, non le parole .. – Rob

3

provare questo

string sentence = "I am good, Is he good"; 


     var words = sentence.Split(new char[]{' ',','}).Distinct(StringComparer.CurrentCultureIgnoreCase); 

     var stringBuilder = new StringBuilder(); 

     foreach(var item in words) 
     { 
      stringBuilder.Append(item); 
      stringBuilder.Append(" "); 
     } 
     Console.Write(stringBuilder); 
     Console.ReadLine(); 
+0

1) 'string.Join' è tuo amico. 2) Questo produce uno spazio finale 3) Non inverte. – CodesInChaos

9

Per inversione di pianura:

String.Join(" ", text.Split(' ').Reverse()) 

Per inversione con la rimozione duplicati:

String.Join(" ", text.Split(' ').Reverse().Distinct()) 

Entrambi funzionano bene per le stringhe contenenti solo spazi come il separatore. Quando si introduce il ,, il problema diventa più difficile. Tanto che è necessario specificare come dovrebbe essere gestito.Ad esempio, dovrebbe "I am good, Is he good" diventare "good he Is am I" o "good he Is , am I"? Il tuo esempio nella domanda modifica il caso di "Is" e raggruppa anche lo ",". Mi sembra sbagliato.

+0

È garantito che 'Distinct' non modifica l'ordine? – raznagul

+0

@raznagul - Sì, è garantito. L'algoritmo attraversa l'enumerabile in ordine e produce solo valori la prima volta che li vede. – Enigmativity