Test auf wiederholte Zeichen in einer Zeichenfolge

8

Ich arbeite mit Strings und habe ein Szenario, in dem ich feststellen muss, ob eine Zeichenfolge (normalerweise eine kleine & lt; 10 Zeichen) wiederholte Zeichen enthält.

%Vor%

Ich kann den string.ToCharArray () durchlaufen und jeden Charakter gegen jedes andere Zeichen im char [] testen, aber ich habe das Gefühl, dass mir etwas offensichtlich fehlt ... vielleicht brauche ich nur Kaffee. Kann jemand helfen?

BEARBEITEN:

Die Zeichenfolge wird sortiert, daher ist die Reihenfolge nicht wichtig, also ABCDA = & gt; AABCD

Die Häufigkeit der Wiederholungen ist ebenfalls wichtig, also muss ich wissen, ob die Wiederholung ein Paar oder Triplett usw. ist.

    
inspite 06.05.2009, 13:24
quelle

11 Antworten

9

Wenn die Zeichenfolge kurz ist, dann ist das Schleifen und Testen möglicherweise die einfachste und effizienteste Methode. Ich meine, Sie könnten einen Hash-Satz erstellen (in jeder Plattform, die Sie verwenden) und die Zeichen durchlaufen, scheitern, wenn der Charakter bereits im Satz ist und sie dem Satz hinzufügen - aber nur das wahrscheinlich einen Vorteil bieten, wenn die Saiten länger sind.

EDIT: Jetzt, da wir wissen, dass es sortiert ist, mquander's Antwort ist die beste IMO. Hier ist eine Implementierung:

%Vor%

Eine kürzere Alternative, wenn es Ihnen nichts ausmacht, die Verwendung des Indexers zu wiederholen:

%Vor%

EDIT: Okay, mit der "Frequenz" -Seite werde ich das Problem ein wenig umdrehen. Ich gehe immer noch davon aus, dass die Zeichenfolge sortiert ist. Was wir also wissen wollen, ist die Länge des längsten Laufs. Wenn keine Wiederholungen vorhanden sind, ist die längste Lauflänge 0 (für eine leere Zeichenfolge) oder 1 (für eine nicht leere Zeichenfolge). Andernfalls sind es 2 oder mehr.

Zuerst eine stringspezifische Version:

%Vor%

Nun können wir dies auch als allgemeine Erweiterungsmethode für IEnumerable<T> :

tun %Vor%

Dann können Sie zum Beispiel "AABCD".LongestRun() aufrufen.

    
Jon Skeet 06.05.2009, 13:27
quelle
16

Wenn die Zeichenfolge sortiert ist, können Sie sich jedes Zeichen der Reihe nach merken und sicherstellen, dass das nächste Zeichen niemals mit dem letzten Zeichen identisch ist.

Anders als bei Strings mit weniger als zehn Zeichen ist es wahrscheinlich genauso schnell oder schneller als alle anderen Dinge, jedes Zeichen gegen den Rest zu testen. Ein Bit-Vektor, wie von einem anderen Kommentator vorgeschlagen, kann schneller sein (hilft, wenn Sie eine kleine Menge von zulässigen Zeichen haben.)

Bonus: Hier ist eine raffinierte LINQ-Lösung, um Jons Funktionalität zu implementieren:

%Vor%

Also, OK, es ist nicht sehr schnell! Du hast ein Problem damit?!

: -)

    
mquander 06.05.2009 13:27
quelle
8

Dies sagt Ihnen sehr schnell wenn eine Zeichenkette Duplikate enthält:

%Vor%

Es prüft nur die Anzahl der einzelnen Zeichen gegenüber der ursprünglichen Länge. Wenn sie anders sind, haben Sie Duplikate ...

Bearbeiten: Ich schätze, das kümmert sich nicht um die Häufigkeit der Duplikate, die du in deinem Schnitt notiert hast ... aber einige andere Vorschläge hier sorgen bereits dafür, also werde ich es nicht tun poste den Code, wie ich eine Anzahl von ihnen bereits feststellst, gibt Ihnen eine einigermaßen elegante Lösung. Ich mag besonders die Implementierung von Joe mit LINQ-Erweiterungen.

    
BenAlabaster 06.05.2009 13:51
quelle
7

Da Sie 3.5 verwenden, können Sie dies in einer LINQ-Abfrage tun:

%Vor%

Für jedes Zeichen, das mehr als einmal in der Eingabe erscheint, erhalten Sie das Zeichen und die Anzahl der Vorkommen.

    
Winston Smith 06.05.2009 13:44
quelle
6

Ich denke, der einfachste Weg, um dies zu erreichen, ist diese einfache Regex

zu verwenden %Vor%

Wenn Sie mehr Informationen über die Übereinstimmung benötigen (Start, Länge usw.)

%Vor%     
xrost 06.05.2009 13:37
quelle
3

Aktualisieren Jetzt benötigen Sie ein Array von Zählern, um eine Zählung aufrechtzuerhalten.

Behalte ein Bit-Array, wobei ein Bit ein eindeutiges Zeichen darstellt. Schalten Sie das Bit ein, wenn Sie auf ein Zeichen stoßen, und führen Sie die Zeichenfolge einmal aus. Eine Zuordnung des Bit-Array-Index und des Zeichensatzes steht Ihnen frei. Brechen Sie, wenn Sie sehen, dass ein bestimmtes Bit bereits aktiviert ist.

    
dirkgently 06.05.2009 13:27
quelle
2

Wie wäre es mit etwas wie:

%Vor%     
CasperT 06.05.2009 13:52
quelle
2
%Vor%

(oder was auch immer das Äquivalent in der Syntax Ihrer Regex-Bibliothek ist)

Dies ist nicht die effizienteste Methode, da es wahrscheinlich auf jedes Zeichen in der Zeichenfolge zurückgeht und dann erneut vorwärts scannt. Und ich befürworte normalerweise keine regulären Ausdrücke. Aber wenn Sie die Kürze wünschen ...

    
Steve Jessop 06.05.2009 13:38
quelle
1

Ich fing an, nach Informationen im Internet zu suchen und kam zu folgender Lösung.

%Vor%

Ich hoffe, es hilft, ich hatte ein Vorstellungsgespräch, in dem der Interviewer mich gebeten hat, das zu lösen, und ich verstehe, dass es eine allgemeine Frage ist.

    
BlackPauler 22.03.2016 14:08
quelle
0

Wenn es keine Reihenfolge gibt, in der Sie arbeiten könnten, könnten Sie ein Wörterbuch verwenden, um die Anzahl zu halten:

%Vor%     
Davy Landman 06.05.2009 14:08
quelle
0

Die von Jon beschriebene Hash-Lösung ist wahrscheinlich die beste. Sie könnten ein HybridDictionary verwenden, da dies gut mit kleinen und großen Datensätzen funktioniert. Wo der Buchstabe der Schlüssel ist und der Wert die Frequenz ist. (Aktualisieren Sie die Häufigkeit jedes Mal, wenn das Hinzufügen fehlschlägt oder das HybridDictionary für .Contains (key) den Wert true zurückgibt)

    
Paul U 06.05.2009 17:03
quelle

Tags und Links