4

我试图解决这个问题。

基本上我需要从字符数组中选择第二个副本。

Input {'x','y','z','x','y'} output: y
Input { 'a', 'a', 'b', 'a', 'c', 'b', 'a', 'c', 'b' } Output: b
Input { 'a','a','a','b','a','c','b','a','c','b' } output: b

编辑:

Input {'a', 'b', 'c', 'b', 'a', 'c', 'b', 'a', 'c', 'b'} Output: a

我试过写这段代码,但如果第一个字符立即重复,它会失败:(有什么帮助纠正这个吗?

 public static char returnSecondDuplicate(char[] arr)
        {
            if (arr.Length == 0)
                throw new ArgumentNullException("empty input");
            var dictionary = new Dictionary<char, int>();
            Char second = '\0';
            int duplicateCount = 0;

            for (int i = 0; i <= arr.Length - 1; i++)
            {

                if (!dictionary.ContainsKey(arr[i]))
                {
                    dictionary.Add(arr[i], 1);
                }
                else
                {
                    duplicateCount++;

                    if (duplicateCount == 2)
                    {
                        second = arr[i];
                    }
                }
            }

            return second;
        }
4

4 回答 4

2

这是适用于给定情况的通用扩展方法:

public static T GetNthDuplicate<T>(this IEnumerable<T> source, int n)
{
    HashSet<T> hashSet = new HashSet<T>();
    return source.Where(item => !hashSet.Add(item))
                 .Distinct().Skip(n - 1) //one based index
                 .FirstOrDefault();
}
于 2013-11-14T12:59:58.757 回答
2

这应该很好地解决它:

var secondDuplicate = input.GroupBy( c => c)
                           .Where( g => g.Count() > 1)
                           .Skip(1)
                           .First()
                           .Key;

首先将它们分组,然后只使用一个元素对所有组进行折扣(因为它们不是重复的),然后取第二个(跳过第一个)

于 2013-11-14T12:43:17.953 回答
1

原始代码的问题是每次看到重复字符时都会增加,但是,您没有检测到它是否已经被考虑在内。一个简单的更改是使用列表(而不是整数)来跟踪重复项。

此外,另一个小的改进(在我看来)是使用while循环而不是 afor因为你只想迭代直到满足某些条件,所以它看起来更合适,例如

public static char returnSecondDuplicate(char[] arr)
{
    if (arr.Length == 0)
        throw new ArgumentNullException("Empty Array passed");
    var dictionary = new Dictionary<char, int>();
    var duplicates = new List<char>();
    Char second = '\0';
    int i = 0;

    while (duplicates.Count != 2 && dictionary.Count != arr.Length)
    {
        if (!dictionary.ContainsKey(arr[i]))
            dictionary.Add(arr[i], 1);
        else if (!duplicates.Contains(arr[i]))
            duplicates.Add(arr[i]); // only add duplicates once (ignoring any duplicate duplicates!)

        second = duplicates.Count == 2 ? arr[i] : second;
        i++;
    }

    return second;
}

看到它运行

于 2013-11-14T12:58:24.420 回答
1

问题是您正在计算总重复次数,而不是单个字符的重复次数。

已经提供了一些 linq 答案,但是如果您想知道如何修复现有代码,可以执行以下操作:

public static char returnSecondDuplicate(char[] arr)
{
    if (arr.Length == 0)
        throw new ArgumentNullException("Empty Array passed");
    var dictionary = new Dictionary<char, int>();
    char firstDuplicate = '\0';

    for (int i = 0; i <= arr.Length - 1; i++)
    {

        if (!dictionary.ContainsKey(arr[i]))
        {
            dictionary.Add(arr[i], 1);
        }
        else if (firstDuplicate == '\0')
        {
            firstDuplicate = arr[i];
        }
        else if(arr[i] != firstDuplicate)
        {
            return arr[i];
        }

    }

    return '\0'; //not found
}

基本上,您必须首先跟踪哪个字母是重复的。一旦你有了第一个副本,检查后续的不是同一个字母。第一个不同的副本是您要返回的内容。

于 2013-11-14T12:53:57.187 回答