Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I quickly tell if a list contains only duplicates?

There are multiple related questions, but I'm looking for a solution specific to my case. There is an array of (usually) 14 integers. How can I quickly tell if each int appears exactly twice (i.e. there are 7 pairs)? The value range is from 1 to 35. The main aspect here is performance.

For reference, this is my current solution. It was written to resemble the spec as closely as possible and without performance in mind, so I'm certain is can be improved vastly:

var pairs = Array
    .GroupBy (x => x)
    .Where (x => x.Count () == 2)
    .Select (x => x.ToList ())
    .ToList ();
IsSevenPairs = pairs.Count == 7;

Using Linq is optional. I don't care how, as long as it's fast :)

Edit: There is the special case that an int appears 2n times with n > 1. In this case the check should fail, i.e. there should be 7 distinct pairs.

Edit: Result I tested Ani's and Jon's solutions with tiny modifications and found during multiple benchmark runs in the target app that Ani's has about twice Jon's throughput on my machine (some Core 2 Duo on Win7-64). Generating the array of ints already takes about as long as the respective checks, so I'm happy with the result. Thanks, all!

like image 989
mafu Avatar asked Nov 15 '10 15:11

mafu


People also ask

How do I check if a list has duplicates?

For this, we will use the count() method. The count() method, when invoked on a list, takes the element as input argument and returns the number of times the element is present in the list. For checking if the list contains duplicate elements, we will count the frequency of each element.

How do you find the number of repeated values in a list in Python?

Operator. countOf() is used for counting the number of occurrences of b in a. It counts the number of occurrences of value. It returns the Count of a number of occurrences of value.


1 Answers

Well, given your exact requirements, we can be a bit smarter. Something like this:

public bool CheckForPairs(int[] array)
{
    // Early out for odd arrays.
    // Using "& 1" is microscopically faster than "% 2" :)
    if ((array.Length & 1) == 1)
    {
        return false;
    }

    int[] counts = new int[32];
    int singleCounts = 0;
    foreach (int item in array)
    {
        int incrementedCount = ++counts[item];
        // TODO: Benchmark to see if a switch is actually the best approach here
        switch (incrementedCount)
        {
            case 1:
                singleCounts++;
                break;
            case 2:
                singleCounts--;
                break;
            case 3:
                return false;
            default:
                throw new InvalidOperationException("Shouldn't happen");
        }
    }
    return singleCounts == 0;
}

Basically this keeps track of how many unpaired values you still have, and has an "early out" if it ever finds three of a kind.

(I don't know offhand whether this will be faster or slower than Ani's approach of incrementing and then checking for unmatched pairs afterwards.)

like image 64
Jon Skeet Avatar answered Oct 01 '22 13:10

Jon Skeet