c# - How can I quickly tell if a list contains only duplicates? -
there multiple related questions, i'm looking solution specific case. there array of (usually) 14 integers. how can tell if each int appears twice (i.e. there 7 pairs)? value range 1 35. main aspect here performance.
for reference, current solution. written resemble spec closely possible , without performance in mind, i'm can improved vastly:
var pairs = array .groupby (x => x) .where (x => x.count () == 2) .select (x => x.tolist ()) .tolist (); issevenpairs = pairs.count == 7;
using linq optional. don't care how, long it's fast :)
edit: there special case int appears 2n times n > 1. in case check should fail, i.e. there should 7 distinct pairs.
edit: result tested ani's , jon's solutions tiny modifications , found during multiple benchmark runs in target app ani's has twice jon's throughput on machine (some core 2 duo on win7-64). generating array of ints takes long respective checks, i'm happy result. thanks, all!
clearly, linq won't provide optimal solution here, although improve current linq solution to:
// checks if sequence consists of items repeated once bool issingledupseq = myseq.groupby(num => num) .all(group => group.count() == 2); // checks if every item comes atleast 1 duplicate bool isdupseq = myseq.groupby(num => num) .all(group => group.count() != 1);
for specific case mention (0 - 31), here's faster, array-based solution. doesn't scale when range of possible numbers large (use hashing solution in case).
// elements inited 0 because default(int) == 0 var timesseenbynum = new int[32]; foreach (int num in myarray) { if (++timesseenbynum[num] == 3) { //quick-reject: number seen thrice return false; } } foreach (int timesseen in timesseenbynum) { if (timesseen == 1) { // rejection case not caught far // if number seen once return false; } } // good, number seen twice or never return true;
edit: fixed bugs pointed out jon skeet. should point out algo smarter , probably faster.
Comments
Post a Comment