How to check number of pairs elements in array? - c#

I am trying to solve a problem but I can't seem to figure out the right way to do it. For example: array []= {1,1,1,1,1,2,3,3,4} . Here pairs of 1 are 2 and a pair of 3 is 1. So total there is 3 pair. I am trying to solve this. Here is the current code situation.
static int PairCounter(int n, int[] ar) {
int temp_n = 0;
//store the array range with constrains
Console.WriteLine("Enter the number of object: ");
temp_n = Console.Convert.ToInt32(Console.ReadLine());
if((temp_n >= 1) || (temp_n <= 100)){
n = temp_n;
}else{
Console.WriteLine("Please enter a value less then 100 and greater then 1.");
temp_n = Console.Convert.ToInt32(Console.ReadLine());
if((temp_n >= 1) || (temp_n <= 100)){
n = temp_n;
}else{
Console.WriteLine("Please rerun the code.");
}
}
//Stores Array with constrains
Console.WriteLine("Enter the number of array: ");
int[] arr = new int[n];
for(int i = 0; i<= n; i++){
arr[i] = Console.Convert.ToInt32(Console.ReadLine());
if((arr[i] >= 1) || (arr[i] <= 100)){
ar[i] = arr[i];
}else{
Console.WriteLine("Please enter a value less then 100 and greater then 1.");
arr[i] = Convert.ToInt32(Console.ReadLine());
if((arr[i] >= 1) || (arr[i] <= 100)){
ar[i] = arr[i];
}else{
Console.WriteLine("Rerun the code");
}
}
}
//copy the array to another array
int[] array3 = new int[n];
for(i=0;i<=n; i++)
{
array3[i]=ar[i];
}
int repeat_counter = 0;
for(int i = 0; i<=n;i++){
if(ar[i].Contains(array3[i])){
repeat_counter++;
}
}
}
Any help is appreciatable.

You can do this in a one liner:
var pairs = ii.GroupBy(i => i).Sum(g => g.Count() / 2);
But yeah, using linq is cheating in the present circumstances. An easy way to solve this is taking advantage that you are counting ints. You can use an array to keep track of how many instances of any given number you find by using that same number as the index:
static int CountPairs(int[] array)
{
var counter = new int[array.Length];
foreach (var i in array)
{
counter[i] += 1;
}
var pairs = 0;
foreach (var count in counter)
{
pairs += count / 2;
}
return pairs;
}
That should also do the trick.
Of course you could generalize this to work with anything, but a simple array won't work anymore, you'd need something a tad more sophisticated: a dictionary. But the idea is the same as the previous solution; simply keeping track of how many times you see any given item:
static int CountPairs<T>(IEnumerable<T> source)
{
var counter = new Dictionary<T, int>();
foreach (var item in source)
{
if (!counter.TryAdd(item, 1))
counter[item] += 1;
}
var pairs = 0;
foreach (var count in counter.Values)
{
pairs += count / 2;
}
return pairs;
}
But...meh, once here, its probably better to simply use the linq one-liner ;)

with Linq its very simple:
var result = array.GroupBy(x => x).Select(x => new {num = x.Key, count = x.Count() / 2});
foreach(var item in result)
Consolve.WriteLine($"{item.count} pair(s) of {item.num}");
To get the total number of pairs:
int total = array.GroupBy(x => x).Sum(x => x.Count());
Consolve.WriteLine($"{total} pair(s) in total");

Related

How can I make so that my Values dont repeat with Random.Range()? [duplicate]

Basically I'm creating a program to randomly generate 6 unique lottery numbers so there is no duplicates in the same line, here is the code I have so far...
//Generate 6 random numbers using the randomiser object
int randomNumber1 = random.Next(1, 49);
int randomNumber2 = random.Next(1, 49);
int randomNumber3 = random.Next(1, 49);
int randomNumber4 = random.Next(1, 49);
int randomNumber5 = random.Next(1, 49);
int randomNumber6 = random.Next(1, 49);
textBox1.Text = randomNumber1.ToString();
textBox2.Text = randomNumber2.ToString();
textBox3.Text = randomNumber3.ToString();
textBox4.Text = randomNumber4.ToString();
textBox5.Text = randomNumber5.ToString();
textBox6.Text = randomNumber6.ToString();
}
I'm getting random numbers but sometimes there is the same number on the same line, how do I make each number unique????
Thanks in advance
You need to store them in a collection and each time you pick a new number you need to make sure it's not present already, otherwise you need to generate a new number until you find a unique number.
Instead of this, I would generate a sequence between 1 and 49, shuffle them and pick 6 number out of the sequence, for example:
var rnd = new Random();
var randomNumbers = Enumerable.Range(1,49).OrderBy(x => rnd.Next()).Take(6).ToList();
You can't. You've only specified that each number be a random number from 1 to 49, not that it shouldn't match any duplicates.
Since you've got a relatively small set of numbers, your best bet is probably to draw the random numbers, put them into a HashSet, then if you need more, pull more. Something like this:
HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < 6) {
numbers.Add(random.Next(1, 49));
}
Here you're taking advantage of the HashSet's elimination of duplicates. This won't work with a List or other collection.
Returning repeat values is a necessity in order for a generator to satisfy a necessary statistical property of randomness: the probability of drawing a number is not dependent on the previous numbers drawn.
You could shuffle the integers in the range 1 to 49 and return the first 6 elements. See http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle for more details on such a shuffler.
However, I think you get a slight statistical bias by doing this.
The best way is probably to use random.Next(1, 49); and reject any repeat. That will be free from statistical bias and the fact that you're only wanting 6 from 49 possibilities, the number of collisions will not slow the algorithm appreciably.
Using this extension method for reservoir sampling:
public static IList<T> TakeRandom<T>(
this IEnumerable<T> source, int count, Random random)
{
var list = new List<T>(count);
int n = 1;
foreach (var item in source)
{
if (list.Count < count)
{
list.Add(item);
}
else
{
int j = random.Next(n);
if (j < count)
{
list[j] = item;
}
}
n++;
}
return list;
}
You can sample your collection like this:
var random = new Random();
var numbers = Enumerable.Range(1, 49).TakeRandom(6, random);
numbers.Shuffle(random);
Note the returned numbers will be uniformly sampled out of all (49 choose 6) possibilities for a set of 6 numbers out of {1, 2, ..., 49}, but they will neither remain in order nor be uniformly shuffled. If you want to have the order randomized as well, you can easily do a standard Fisher-Yates shuffle afterwards.
public static void Shuffle<T>(this IList<T> list, Random random)
{
for (int i = 0; i < list.Count; i++)
{
int j = random.Next(i, list.Count);
T temp = list[j];
list[j] = list[i];
list[i] = temp;
}
}
Note a more heavily optimized version of Fisher-Yates shuffle can be found in this answer: Randomize a List<T>
List<int> aux = new List<int>();
while(aux.Count < 6)
{
int rnd = random.Next(1,49);
if(!aux.Contains(rnd))aux.add(rnd);
}
if you put all Texbox in the same panel you can do that
int j = 0;
foreach(Control x in MyPanel.Controls)
{
if(x is TexBox)
{
x.Text = aux[j].toString();
j++;
}
}
It's my solution: generate array of number
/// <summary>
/// auto generate a array with number element and max value is max
/// </summary>
/// <param name="number">number element of array</param>
/// <param name="max">max value of array</param>
/// <returns>array of number</returns>
public static int[] createRandomArray(int number, int max)
{
List<int> ValueNumber = new List<int>();
for (int i = 0; i < max; i++)
ValueNumber.Add(i);
int[] arr = new int[number];
int count = 0;
while (count < number)
{
Random rd = new Random();
int index = rd.Next(0,ValueNumber.Count -1);
int auto = ValueNumber[index];
arr[count] = auto;
ValueNumber.RemoveAt(index);
count += 1;
}
return arr;
}
It's too late but I use a Method named M_Randomizer created by me. It may look as too much work, but it's technique is different from traditional which is based on generating a random number and checking the previously generated list for uniqueness. This code while generating a new random number, never looks for the previously generated. And if we talk about touching all combinations, I have tested this method till 9 factorial, maybe little bias for some but it touches all.
using System;
class Randomizer
{
public int[] M_Randomizer(int x)
{
bool b = false;
if (x < -1)
{
b = true;
x = -1 * x;
}
if(x == -1)
x = 0;
if (x < 2)
return new int[x];
int[] site;
int k = new Random(Guid.NewGuid().GetHashCode()).Next() % 2;
if (x == 2)
{
site = new int[2];
site[0] = k;
site[1] = 1 - site[0];
return site;
}
else if (x == 3)
{
site = new int[3];
site[0] = new Random(Guid.NewGuid().GetHashCode()).Next(0, 3);
site[1] = (site[0] + k + 1) % 3;
site[2] = 3 - (site[0] + site[1]);
return site;
}
site = new int[x];
int a = 0, m = 0, n = 0, tmp = 0;
int[] p = M_Randomizer(3);
int[] q;
if (x % 3 == 0)
q = M_Randomizer(x / 3);
else
q = M_Randomizer((x / 3) + 1);
if (k == 0)
{
for (m = 0; m < q.Length; m++)
{
for (n = 0; n < p.Length && a < x; n++)
{
tmp = (q[m] * 3) + p[n];
if (tmp < x)
{
site[a] = tmp;
a++;
}
}
}
}
else
{
while (n < p.Length)
{
while (a < x)
{
tmp = (q[m] * 3) + p[n];
if (tmp < x)
{
site[a] = tmp;
a++;
}
m = m + k;
if (m >= q.Length)
break;
}
m = m % q.Length;
n++;
}
}
a = (new Random(Guid.NewGuid().GetHashCode()).Next() % 2) + 1;
k = new Random(Guid.NewGuid().GetHashCode()).Next() % 10;
if (k > 5)
for (int i = a; i < k; i++)
while (a < site.Length)
{
if (k % (a + 1) == 0)
{
tmp = site[a - 1];
site[a - 1] = site[a];
site[a] = tmp;
}
a = a + 2;
}
k = new Random(Guid.NewGuid().GetHashCode()).Next() % 10;
if (k > 5)
{
n = x / 2;
k = 0;
if (x % 2 != 0)
k = (new Random(Guid.NewGuid().GetHashCode()).Next() % 2);
p = new int[n + k];
m = (x - n) - k;
for (a = 0; m < x; a++, m++)
p[a] = site[m];
m = n + k;
for (a = (x - m) - 1; a >= 0; a--, m++)
site[m] = site[a];
for (a = 0; a < p.Length; a++)
site[a] = p[a];
}
int[] site2;
int[] site3 = new int[x];
if (b)
return site;
else
site2 = M_Randomizer(-1 * x);
for (a = 0; a < site.Length; a++)
site3[site2[a]] = site[a];
return site3;
}
public int[] M_Randomizer(int x, int start)
{
int[] dm = M_Randomizer(x);
for(int a = 0; a < x; a++)
dm[a] = dm[a] + start;
return dm;
}
}
Look at using an array to hold your 6 numbers.
Each time you generate one, loop through the array to make sure it is not already there. If it is, then generate another & loop again until you have a non-match.
It's so easy with array and OOP (Object Oriented Programming). Before you start you have to add Linq (using System.Linq) library to your project.
Random random = new Random();
int[] array = new int[6];
int number;
for (int i = 0; i < 6; i++)
{
number = random.Next(1, 50);
if (!array.Contains(number)) //If it's not contains, add number to array;
array[i] = number;
else //If it contains, restart random process
i--;
}
for (int i = 1; i < 7; i++)
{
foreach (Control c in this.Controls) //Add random numbers to all Textboxes
{
if (c is TextBox && c.Name.EndsWith(i.ToString()))
{
c.Text = array[i - 1].ToString();
}
}
}
A functional approach could be to generate an infinite sequence of random numbers, filter out non-unique numbers and take the number of unique numbers you need.
For example:
private IEnumerable<int> RandomDigitStream(int seed)
{
Random random = new Random(seed);
while (true)
{
yield return random.Next(DIGIT_MIN, DIGIT_MAX);
}
}
private List<int> GenerateUniqueRandomNumbers(int seed, int count)
{
// Assert that DIGIT_MAX - DIGIT_MIN > count to ensure
// algorithm can finish
return RandomDigitStream(seed)
.Distinct()
.Take(count)
.ToList();
}
The efficiency of this algorithm is mainly dependent on how Distinct is implemented by the .NET team. Its memory usage would grow with the number of digits you require and the range of digits produced by the random function. It also has an unpredictable running time as it depends on the probability distribution of the random function. In fact it is possible for this algorithm to get stuck in an infinite loop if the range of digits produced by the random algorithm is less than the number of digits you require.
Looking at it practically however, it should be fine for a small amount of digits but if you are looking at a large number (100 +) you might want to look at other methods.
It would be more efficient to craft a random algorithm that only produces unique numbers in the first place if that is even possible without using a lookup table.
Here is a small program using recursion to generate number lines, and also uses recursion to randomize and get unique numbers.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static Random random;
public static List<int> lottoNumbers = Enumerable.Range(1, 49).ToList();
public static void Main()
{
random = new Random((int)DateTime.Now.Ticks);
var LinesToGenerate = 10;
GenerateNumbers(LinesToGenerate);
}
public static void GenerateNumbers(int LineCount)
{
int[] SelectedNumbers = new int[6];
for (var i = 0; i < 6; i++)
{
var number = GetRandomNumber(lottoNumbers.ToArray());
while (SelectedNumbers.Contains(number))
number = GetRandomNumber(lottoNumbers.ToArray());
SelectedNumbers[i] = number;
}
var numbersOrdered = SelectedNumbers.OrderBy(n => n).Select(n => n.ToString().PadLeft(2, '0'));
Console.WriteLine(string.Join(" ", numbersOrdered));
if (LineCount > 1)
GenerateNumbers(--LineCount);
}
//Recursively and randomly removes numbers from the array until only one is left, and returns it
public static int GetRandomNumber(int[] arr)
{
if (arr.Length > 1)
{
//Remove random number from array
var r = random.Next(0, arr.Length);
var list = arr.ToList();
list.RemoveAt(r);
return GetRandomNumber(list.ToArray());
}
return arr[0];
}
}
Yes. Use array.
Loop how many times you want:
Generate a random number,
Loop through array and compare all with the generated number.
If there's a match then loop again till there's no match.
Then store it.
Done:)

Lottery program that generates 6 random numbers between 1 and 59 C#

I have created a simple program which randomly generates 6 winning numbers. While the program works, I would also like for it to ensure that the same number isn't outputted twice as well as sorting them into numerical order when outputted. How would I go about doing such a thing while sticking to similar techniques already used? My code is down below. Any help is very much appreciated.
int temp;
int[] lotto = new int[6];
Random rand = new Random();
for (int i = 0; i < 6; i++)
{
temp = rand.Next(1, 59);
lotto[i] = temp;
}
Console.Write($"The lotterry winning numbers are: ");
for (int i = 0; i < 6; i++)
{
Console.Write(lotto[i] + " ");
}
Console.ReadKey();
Based on a Fisher-Yates shuffle, but saves some work because we know we don't need all the values (if we only need 6 values out of 10 million potentials, we only need to take the first six iterations of the fisher-yates algorithm).
public IEnumerable<int> DrawNumbers(int count, int MaxNumbers)
{
var r = new Random(); //ideally, make this a static member somewhere
var possibles = Enumerable.Range(1, MaxNumbers).ToList();
for (int i = 0; i < count; i++)
{
var index = r.Next(i, MaxNumbers);
yield return possibles[index];
possibles[index] = possibles[i];
}
}
var lottoNumbers = DrawNumbers(6, 59);
Console.Write("The lotterry winning numbers are: ");
Console.WriteLine(string.Join(" ", lottoNumbers.OrderBy(n => n)));
See it work here:
https://dotnetfiddle.net/NXYkpU
You can use Linq to create sequence [1..59] and order it by random to shuffle it.
Random rand = new Random();
var winners = Enumerable.Range(1, 59)
.OrderBy(x => rand.Next())
.Take(6)
.OrderBy(x => x)
.ToList();
Console.WriteLine(String.Join(" ", winners));
int temp;
int[] lotto = new int[6];
Random rand = new Random();
int i = 0;
while(i < 6)
{
temp = rand.Next(1, 59);
//check if lotto contains just generated number, if so skip that number
bool alreadyExist = false;
foreach (int item in lotto)
{
if (item == temp)
{
alreadyExist = true;
break;
}
}
if (alreadyExist)
continue;
lotto[i] = temp;
i++;
}
Console.Write($"The lotterry winning numbers are: ");
// Sort array in ascending order.
Array.Sort(lotto);
for (int j = 0; j < 6; j++)
{
Console.Write(lotto[j] + " ");
}
Console.ReadKey();
I would probably do it Dmitri's way because it is quick and obvious and performance isn't that important with an array this size.
But just for fun, this is slightly more efficient.
IEnumerable<int> GetNumbers(int min, int max, int count)
{
var random = new Random();
var size = max - min + 1;
var numbers = Enumerable.Range(min, size).ToArray();
while (count > 0)
{
size--;
var index = random.Next(0, size);
yield return numbers[index];
numbers[index] = numbers[size];
count--;
}
}
This solution creates an array containing all possible values and selects them randomly. Each time a selection is made, the array is "shrunk" by moving the last element to replace the element that was chosen, preventing duplicates.
To use:
var numbers = GetNumbers(1, 59, 6).ToList();
foreach (var number in numbers.OrderBy(x => x))
{
Console.WriteLine(number);
}

How to convert For Loop results into an Array then count the integers of the resulting Array in C#?

In C#, how would I go about converting the result of a For Loop into an Array and count (Display on the Console) the number of integers stored in that converted array?
Please see below for what I have thus far:
for (int i = 1; i < 100; i++)
{
if (i % 3 == 0)
{
Console.WriteLine(i);
}
}
And feel free to let me know if there is a different way to count the results of the code I have above.
Please let me know what you think.
There are a few different ways to accomplish what you're after. You can use a for-loop as you've done and accomplish it like so:
var list = new List<int>();
var sum = 0;
for (var i = 1; i < 100; i++)
{
if (i % 3 != 0)
continue;
list.Add(i);
Console.WriteLine(i);
sum += i;
}
Console.WriteLine($"Count: {list.Count}");
Console.WriteLine($"Sum: {sum}");
You could also accomplish this with Linq:
var numbers = Enumerable.Range(1, 99)
.Where(i => i % 3 == 0)
.ToList();
var sum = numbers.Sum();
numbers.ForEach(Console.WriteLine);
Console.WriteLine($"Count: {numbers.Count}");
Console.WriteLine($"Sum: {sum}");
You can use List for that purpose:
var list = new List<int>();
for (int i = 1; i < 100; i++)
{
if (i % 3 == 0)
{
list.Add(i);
Console.WriteLine(i);
}
}
Console.WriteLine(list.Count);
There is no need to insert the numbers into a collection to count them. Just use a variable as counter
int count = 0;
for (int i = 1; i < 100; i++)
{
if (i % 3 == 0)
{
count++; // Increments count by 1.
Console.WriteLine(i);
}
}
Console.WriteLine("The count is " + count);
List<int> myList = new List<int>();
for (int i = 1; i < 100; i++) {
if (i % 3 == 0) {
Console.WriteLine(i);
myList.Add(i);
}
}
Console.WriteLine(myList.Count);
//if you want an array....
int[] myArray;
myArray = myList.ToArray();

issues on using mode in C#

I'm having issues with my Mode and getting it to let me input more then 10 numbers!
Those are the two issues I am having with my code.
public static void Main(string[] args)
{
int[] myNums = new int[10];
int number = 0;
int count = 0;
Console.WriteLine("--Nmber Modifier--\n");
Console.WriteLine("Entering a number that is no between 1 and 10 will end your process");
do// limited to 10 HELP
{
number = Util.PromptForInt("Enter a number between 1 and 10 : ");
if ((number <= 10) && (number >= 1))
{
myNums[count] = number;
}
count++;
}
while ((number <= 10) && (number >= 1));
Array.Sort(myNums);
Console.WriteLine("Average number is : " + MeantAverage(myNums));
Console.WriteLine("Largest Number is : " + LargestNum(myNums));
Console.WriteLine("Smallest Number is : " + SmallestNum(myNums));
Console.WriteLine("Most common number is : " + Mode(myNums));
Console.ReadLine();
}
static double MeantAverage(int[] nums)
{
double dMeanAverage;
double dSum = 0;
var groups = nums.GroupBy(item => item);
foreach (var group in groups)
{
dSum = group.Key + dSum;
}
dMeanAverage = dSum / nums[nums.Length - 1];
return Math.Round(dMeanAverage, 2);
}
static int LargestNum(int[] nums)
{
int highestNum;
highestNum = nums[nums.Length - 1];
return highestNum;
}
static int SmallestNum(int[] nums)
{
int lowest = 0;
for (int b = 0; b < nums.Length; b++)
{
if (nums[b] > lowest)
{
lowest += nums[b];
return lowest;
}
} return lowest;
}
static int Mode(int[] nums)
{
// issues with mode
int modes = 0;
var modeGroup = nums.GroupBy(v => v);
int max = modeGroup.Max(g => g.Count());
modes = modeGroup.First(g => g.Count() == max).Key;
return modes;
}
}
}
You created an array of ten numbers:
int[] myNums = new int[10];
So while your loop doesn't restrict you to 10 numbers because you don't check against count, the system does because as soon as you try to access the 10th element (myNums[10]) you will get an IndexOutOfRangeException.
Since you don't catch it anywhere, its just going to terminate your program.
To solve your problem:
Check against count so you don't input too many numbers!
If you need a variable length collection, use a collection built for that like List<T> instead of an array. Arrays are fixed-length (mostly), and the way around that is a horrible misuse of the array semantic.
Modified code somewhat, intention is the same though.
You forgot to check against count in the while case
You will crash on '0' inputs (no safe guard against empty array)
Changed Mode to merge items and then sort descending
var myNums = new List<int>(10);
for(int i=0; i < 10; ++i)
{
int number = Utils.PromptForInt("Enter a number between 1 and 10 : ");
if(number > 10 || number < 1)
break;
myNums.Add(number);
}
if(myNums.Count < 1)
return; //no item input, do something
myNums.Sort();
Console.WriteLine("Average: {0}", myNums.Sum() / (double)myNums.Count);
Console.WriteLine("Largest: {0}", myNums[myNums.Count - 1]);
Console.WriteLine("Smallest: {0}", myNums[0]);
var result = myNums.GroupBy(n => n)
.Select(c => new { Key = c.Key, total = c.Count() })
.OrderByDescending( a => a.total);
Console.WriteLine("Most common: {0}, used {1} times", result.First().Key, result.First().total);

How to get the most common value in an Int array? (C#)

How to get the most common value in an Int array using C#
eg: Array has the following values: 1, 1, 1, 2
Ans should be 1
var query = (from item in array
group item by item into g
orderby g.Count() descending
select new { Item = g.Key, Count = g.Count() }).First();
For just the value and not the count, you can do
var query = (from item in array
group item by item into g
orderby g.Count() descending
select g.Key).First();
Lambda version on the second:
var query = array.GroupBy(item => item).OrderByDescending(g => g.Count()).Select(g => g.Key).First();
Some old fashioned efficient looping:
var cnt = new Dictionary<int, int>();
foreach (int value in theArray) {
if (cnt.ContainsKey(value)) {
cnt[value]++;
} else {
cnt.Add(value, 1);
}
}
int mostCommonValue = 0;
int highestCount = 0;
foreach (KeyValuePair<int, int> pair in cnt) {
if (pair.Value > highestCount) {
mostCommonValue = pair.Key;
highestCount = pair.Value;
}
}
Now mostCommonValue contains the most common value, and highestCount contains how many times it occured.
I know this post is old, but someone asked me the inverse of this question today.
LINQ Grouping
sourceArray.GroupBy(value => value).OrderByDescending(group => group.Count()).First().First();
Temp Collection, similar to Guffa's:
var counts = new Dictionary<int, int>();
foreach (var i in sourceArray)
{
if (!counts.ContainsKey(i)) { counts.Add(i, 0); }
counts[i]++;
}
return counts.OrderByDescending(kv => kv.Value).First().Key;
public static int get_occure(int[] a)
{
int[] arr = a;
int c = 1, maxcount = 1, maxvalue = 0;
int result = 0;
for (int i = 0; i < arr.Length; i++)
{
maxvalue = arr[i];
for (int j = 0; j <arr.Length; j++)
{
if (maxvalue == arr[j] && j != i)
{
c++;
if (c > maxcount)
{
maxcount = c;
result = arr[i];
}
}
else
{
c=1;
}
}
}
return result;
}
Maybe O(n log n), but fast:
sort the array a[n]
// assuming n > 0
int iBest = -1; // index of first number in most popular subset
int nBest = -1; // popularity of most popular number
// for each subset of numbers
for(int i = 0; i < n; ){
int ii = i; // ii = index of first number in subset
int nn = 0; // nn = count of numbers in subset
// for each number in subset, count it
for (; i < n && a[i]==a[ii]; i++, nn++ ){}
// if the subset has more numbers than the best so far
// remember it as the new best
if (nBest < nn){nBest = nn; iBest = ii;}
}
// print the most popular value and how popular it is
print a[iBest], nBest
Yet another solution with linq:
static int[] GetMostCommonIntegers(int[] nums)
{
return nums
.ToLookup(n => n)
.ToLookup(l => l.Count(), l => l.Key)
.OrderBy(l => l.Key)
.Last()
.ToArray();
}
This solution can handle case when several numbers have the same number of occurences:
[1,4,5,7,1] => [1]
[1,1,2,2,3,4,5] => [1,2]
[6,6,6,2,2,1] => [6]

Categories