2015-11-12 7 views
7

Ich versuche, diese Frage zu lösen: Schreiben Sie eine Funktion, die den Null-basierten Index des längsten Laufs in einer Zeichenfolge findet. Ein Lauf ist eine fortlaufende Sequenz desselben Zeichens. Wenn es mehr als einen Lauf mit der gleichen Länge gibt, geben Sie den Index des ersten zurück.Index der längsten Lauf C#

Zum Beispiel IndexOfLongestRun ("abbcccddddcccbba") sollte 6 als längste Abfahrt Rückkehr ist dddd und es erscheint zuerst auf Index 6.

Nach was ich getan habe:

private static int IndexOfLongestRun(string str) 
    { 
     char[] array1 = str.ToCharArray(); 
     //Array.Sort(array1); 
     Comparer comparer = new Comparer(); 
     int counter =1; 
     int maxCount = 0; 
     int idenxOf = 0; 

     for (int i =0; i<array1.Length-1 ; i++) 
     { 
      if (comparer.Compare(array1[i],array1[i+1]) == 0) 
      { 
       counter++; 
      } 
      else { 
       if(maxCount < counter) 
       { 
        maxCount = counter; 
        idenxOf = i - counter + 1; 
       } 
       counter = 1; 
      } 
     } 
     return idenxOf ; 
    } 
} 

public class Comparer : IComparer<char> 
{ 
    public int Compare(char firstChar, char nextChar) 
    { 
     return firstChar.CompareTo(nextChar); 
    } 
} 

Das Problem ist, dass, wenn ich zum letzten Index zum Beispiel "abbccaaaaaaaaaa" , die in diesem Fall ist, und wenn i=14 (nimmt diese Zeichenfolge als Beispiel) und wenn i<array1.Length-1 Statment ist falsch, die for-Schleife springt direkt auf return indexOf; und den falschen Index zurück Ich versuche herauszufinden, ho w, um den Forloop zu forcieren, um die Implementierung fortzusetzen, damit idnxOf in den richtigen Index geändert werden kann. Irgendwelche Hilfe bitte?

+0

ja am Ende Klammer der for-Schleife –

+0

ohh leider meine ich indexOf –

+2

warum Sie comparer Zeichen für den Vergleich verwendet? warum nicht direkt vergleichen? –

Antwort

3

Sie können überprüfen, ob für jede Iteration ein neuer bester Score erreicht wird, wenn current == previous. Minimal langsamer, aber es ermöglicht Ihnen kürzeren Code zu schreiben, indem eine zusätzliche Überprüfung nach der Schleife Weglassen:

int IndexOfLongestRun(string input) 
{ 
    int bestIndex = 0, bestScore = 0, currIndex = 0; 
    for (var i = 0; i < input.Length; ++i) 
    { 
     if (input[i] == input[currIndex]) 
     { 
      if (bestScore < i - currIndex) 
      { 
       bestIndex = currIndex; 
       bestScore = i - currIndex; 
      } 
     } 
     else 
     { 
      currIndex = i; 
     } 
    } 
    return bestIndex; 
} 
+0

Yeb, das ist eine gute Lösung! –

+0

Bro, ich sehe nur nicht den Vorteil, '++ i' anstelle von'i ++ 'zu verwenden, weil beide funktionieren sollten? –

+0

In einzelnen Anweisungen werden beide gut funktionieren. Ich persönlich bevorzuge ++ i über i ++, und ich versuche, es in ambigen Situationen überhaupt nicht zu verwenden. Werfen Sie einen Blick auf http://stackoverflow.com/questions/484462/difference-between-i-and-i-in-a-loop für eine detailliertere Erklärung ihrer Unterschiede. – Kvam

2

Fördern die Schleifenvariable i auf Verfahren Umfang und wiederholen den Bedingungsblock if (maxCount < Zähler) {...} direkt nach dem Schleifenausgang. Somit führt es ein weiteres Mal, nachdem die Schleife

private static int IndexOfLongestRun(string str) 
{ 
    char[] array1 = str.ToCharArray(); 
    //Array.Sort(array1); 
    Comparer comparer = new Comparer(); 
    int counter = 1; 
    int maxCount = 0; 
    int idenxOf = 0; 

    int i; 
    for (i = 0; i < array1.Length - 1; i++) 
    { 
     if (comparer.Compare(array1[i], array1[i + 1]) == 0) 
     { 
      counter++; 
     } 
     else 
     { 
      if (maxCount < counter) 
      { 
       maxCount = counter; 
       idenxOf = i - counter + 1; 
      } 
      counter = 1; 
     } 
    } 
    if (maxCount < counter) 
    { 
     maxCount = counter; 
     idenxOf = i - counter + 1; 
    } 
    return idenxOf; 
} 
+0

Das könnte ja helfen, aber ich versuche, bessere Lösung zu finden :) danke für Ihre Mühe, eh bro! –

+0

Sie suchen nach einem besseren. OK. –

+0

Ich weiß, dass dies mit Linq gelöst werden könnte, aber ich bin nicht so gut bei Linq! –

0

vervollständigt Dies wird -1 zurück, wenn die Zeichenfolge leer ist, und Sie haben die Flexibilität, den Index zurückkehrt und die Zählung auf Ihrer Spezifikation abhängig.

 string myStr = "aaaabbbbccccccccccccdeeeeeeeee"; 

     var longestIndexStart = -1; 
     var longestCount = 0; 
     var currentCount = 1; 
     var currentIndexStart = 0; 

     for (var idx = 1; idx < myStr.Length; idx++) 
     { 
      if (myStr[idx] == myStr[currentIndexStart]) 
       currentCount++; 
      else 
      { 
       if (currentCount > longestCount) 
       { 
        longestIndexStart = currentIndexStart; 
        longestCount = currentCount; 
       } 

       currentIndexStart = idx; 
       currentCount = 1; 
      } 
     } 

     return longestIndexStart; 
1

Wie üblich spät, aber der Beitritt zur Partei. Ein natürlicher klassischer Algorithmus:

static int IndexOfLongestRun(string input) 
{ 
    int longestRunStart = -1, longestRunLength = 0; 
    for (int i = 0; i < input.Length;) 
    { 
     var runValue = input[i]; 
     int runStart = i; 
     while (++i < input.Length && input[i] == runValue) { } 
     int runLength = i - runStart; 
     if (longestRunLength < runLength) 
     { 
      longestRunStart = runStart; 
      longestRunLength = runLength; 
     } 
    } 
    return longestRunStart; 
} 

Am Ende haben Sie beide längste Lauf Index und Länge.

0

Die akzeptierte Antwort von Kvam funktioniert gut für kleine Strings, aber wenn die Länge 100.000 Zeichen erreicht (und vielleicht wird dies nicht benötigt), ist ihre Effizienz verloren.

public static int IndexOfLongestRun(string str) 
    { 
     Dictionary<string, int> letterCount = new Dictionary<string, int>(); 

     for (int i = 0; i < str.Length; i++) 
     { 
      string c = str.Substring(i, 1);      

      if (letterCount.ContainsKey(c)) 

       letterCount[c]++; 
      else 

       letterCount.Add(c, 1); 
     } 

     return letterCount.Values.Max(); 
    } 

Diese Lösung ist doppelt so schnell wie Kvam mit großen Saiten. Es gibt vielleicht andere Optimierungen.

0
public static int IndexOfLongestRun(string str) 
    { 
     var longestRunCount = 1; 
     var longestRunIndex = 0; 
     var isNew = false; 

     var dic = new Dictionary<int, int>(); 

     for (var i = 0; i < str.Length - 1; i++) 
     { 
      if (str[i] == str[i + 1]) 
      { 
       if (isNew) longestRunIndex = i; 
       longestRunCount++; 
       isNew = false; 
      } 
      else 
      { 
       isNew = true; 
       dic.Add(longestRunIndex, longestRunCount); 
       longestRunIndex = 0; 
       longestRunCount = 1; 
      } 
     } 

     return dic.OrderByDescending(x => x.Value).First().Key; 
    } 
+0

das sieht gut aus und einfach. –

Verwandte Themen