测试字符串中重复的字符

ins*_*ite 8 c# string algorithm

我正在用字符串做一些工作,我有一个场景,我需要确定一个字符串(通常是一个小的<10个字符)是否包含重复的字符.

`ABCDE`  // does not contain repeats 
`AABCD`  // does contain repeats, ie A is repeated
Run Code Online (Sandbox Code Playgroud)

我可以循环遍历string.ToCharArray()并测试char []中每个其他角色的每个角色,但我觉得我错过了一些明显的东西....也许我只需要咖啡.有人可以帮忙吗?

编辑:

字符串将被排序,因此顺序并不重要,因此ABCDA => AABCD

重复的频率也很重要,所以我需要知道重复是双重还是三重等.

mqp*_*mqp 16

如果字符串已排序,您可以依次记住每个字符并检查以确保下一个字符永远不会与最后一个字符相同.

除此之外,对于十个字符以下的字符串,仅仅针对所有其他字符测试每个字符可能与大多数其他事物一样快或更快.另一位评论者建议的位向量可能更快(如果您有一小组合法字符,则会有所帮助.)

Bonus:这是一个实现Jon功能的灵活的LINQ解决方案:

int longestRun =
    s.Select((c, i) => s.Substring(i).TakeWhile(x => x == c).Count()).Max();
Run Code Online (Sandbox Code Playgroud)

所以,好吧,它不是很快!你对此有看法?!

:-)


Jon*_*eet 9

如果字符串很短,那么循环和测试可能是最简单和最有效的方法.我的意思是你可以创建一个哈希集(在你正在使用的任何平台上)并迭代字符,如果字符已经在集合中并且将其添加到集合中则失败 - 但是这只能提供任何好处字符串更长.

编辑:现在我们知道它的排序,mquander的答案是最好的一个IMO.这是一个实现:

public static bool IsSortedNoRepeats(string text)
{
    if (text.Length == 0)
    {
        return true;
    }
    char current = text[0];
    for (int i=1; i < text.Length; i++)
    {
        char next = text[i];
        if (next <= current)
        {
            return false;
        }
        current = next;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

如果您不介意重复使用索引器,则可以选择较短的替代方法:

public static bool IsSortedNoRepeats(string text)
{
    for (int i=1; i < text.Length; i++)
    {
        if (text[i] <= text[i-1])
        {
            return false;
        }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

编辑:好的,在"频率"方面,我会把问题转过来.我仍然会假设字符串已经排序,所以我们想知道的是最长运行的长度.如果没有重复,则最长的运行长度将为0(对于空字符串)或1(对于非空字符串).否则,它将是2或更多.

首先是特定于字符串的版本:

public static int LongestRun(string text)
{
    if (text.Length == 0)
    {
        return 0;
    }
    char current = text[0];
    int currentRun = 1;
    int bestRun = 0;

    for (int i=1; i < text.Length; i++)
    {
        if (current != text[i])
        {
            bestRun = Math.Max(currentRun, bestRun);
            currentRun = 0;
            current = text[i];
        }
        currentRun++;
    }
    // It's possible that the final run is the best one
    return Math.Max(currentRun, bestRun);
}
Run Code Online (Sandbox Code Playgroud)

现在我们也可以将其作为一般扩展方法IEnumerable<T>:

public static int LongestRun(this IEnumerable<T> source)
{
    bool first = true;
    T current = default(T);
    int currentRun = 0;
    int bestRun = 0;

    foreach (T element in source)
    {
        if (first || !EqualityComparer<T>.Default(element, current))
        {
            first = false;
            bestRun = Math.Max(currentRun, bestRun);
            currentRun = 0;
            current = element;
        }
    }
    // It's possible that the final run is the best one
    return Math.Max(currentRun, bestRun);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以打个电话"AABCD".LongestRun().


Ben*_*ter 8

如果字符串包含重复项,这将告诉您:

bool containsDups = "ABCDEA".Length != s.Distinct().Count();
Run Code Online (Sandbox Code Playgroud)

它只是根据原始长度检查不同字符的数量.如果它们不同,你就有重复......

编辑:我想这并不需要你在你的编辑,虽然指出了DUP频率的照顾......但这里的一些其他建议已照顾到这一点,所以我不会发布的代码,因为我注意到其中一些已经给你一个相当优雅的解决方案.我特别喜欢Joe使用LINQ扩展的实现.


Win*_*ith 7

由于您使用的是3.5,因此可以在一个LINQ查询中执行此操作:

var results = stringInput
  .ToCharArray() // not actually needed, I've left it here to show what's actually happening
  .GroupBy(c=>c)
  .Where(g=>g.Count()>1)
  .Select(g=>new {Letter=g.First(),Count=g.Count()})
;
Run Code Online (Sandbox Code Playgroud)

对于在输入中出现多次的每个字符,这将为您提供字符和出现次数.


xro*_*ost 6

我认为最简单的方法是使用这个简单的正则表达式

bool foundMatch = false;
foundMatch = Regex.IsMatch(yourString, @"(\w)\1");
Run Code Online (Sandbox Code Playgroud)

如果您需要有关比赛的更多信息(开始,长度等)

        Match match = null;
    string testString = "ABCDE AABCD";
    match = Regex.Match(testString, @"(\w)\1+?");
    if (match.Success)
    {
        string matchText = match.Value; // AA
        int matchIndnex = match.Index;  // 6
        int matchLength = match.Length; // 2
    }
Run Code Online (Sandbox Code Playgroud)