How to find the nth duplicate from an array

I tried to solve the problem.

Basically I need to select a second duplicate from a character array.

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

EDIT:

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

I tried to write this piece of code, but it fails if the first character repeats immediately :( Any help in fixing this?

 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
source share
4 answers

The problem is that you are counting the number of full duplicates, not the number of duplicates of one character.

Some answers on linq have been provided, but if you want to know how to fix existing code, you can do something like this:

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
}

, , . , , - . , , .

+1

:

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

, ( ), ( )

+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();
}
+2

, , , , . ( ) .

Also, another small improvement (in my opinion) would be to use a loop whileinstead for, because you only want to iterate until some condition is met, so it seems like this is better suited, for example.

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;
}

See how it works

+1
source

All Articles