Наиболее частое число в массиве

У меня есть этот массив, я написал функцию MostFreq, которая принимает массив целых чисел и возвращает 2 значения: чем чаще число в массиве и его частота проверяют этот код, тем меньше, чем вы думаете? есть ли лучший способ сделать это?

static void Main()
{ 
    int [] M={4,5,6,4,4,3,5,3};
    int x;
    int f=MyMath.MostFreq(M,out x );
    console.WriteLine("the most Frequent Item = {0} with frequency = {1}",x,f);
}

=====

в классе Mymath

public static int MostFreq(int[] _M, out int x)
{
    //First I need to sort the array in ascending order
    int Max_Freq, No_Freq, i, k;
    Array.Sort(_M);                         
    k = _M[0];
    Max_Freq = 0; i = 0; x = 0;
    while (i < _M.Length)
    {
        //No_Freq= the frequency of the current number
        No_Freq = 0;
        //X here is the number which is appear in the array Frequently 
        while (k == _M[i])
        {
            No_Freq++;
            i++;
            if (i == _M.Length) 
                break;
        }
        if (No_Freq > Max_Freq)
        {
            //so it will be printed the same
            Max_Freq = No_Freq;
            x = k;
        }
        if (i < _M.Length) k = _M[i];
    }
    return (Max_Freq);
}

Ответ 1

LINQ. Я знаю, что это в VB, но вы должны иметь возможность преобразовать его в С#:

Dim i = From Numbers In ints _
            Group Numbers By Numbers Into Group _
            Aggregate feq In Group Into Count() _
            Select New With {.Number = Numbers, .Count = Count}

EDIT: теперь также на С#:

var i = from numbers in M
                group numbers by numbers into grouped
                select new { Number = grouped.Key, Freq = grouped.Count()};

Ответ 2

Предполагая, что вы не можете использовать LINQ, я бы, вероятно, подошел к алгоритму следующим образом:

  • Создать словарь ключа/значения
  • Итерируйте свой массив, добавьте ключ для словаря для каждого уникального элемента, увеличивайте значение каждый раз, когда этот элемент повторяется.
  • Пройдите ключи словаря и верните элементу с самым высоким значением.

Это не отличное решение, но оно простое, ContainsKey - это поиск O (1), поэтому вы будете в большей степени повторять свой массив дважды.

Ответ 3

С точки зрения программного обеспечения я ожидал бы функцию MostFreq, чтобы вернуть элемент с самой высокой частотой - не самой частотой. Я бы переключил ваши и возвращаемые значения.

Ответ 4

Вы можете исключить сортировку, которую вы делаете в начале, итерации всего массива один раз, подсчет количества раз, когда вы сталкиваетесь с каждым значением во временном массиве, а затем итерации временного массива для максимального числа. Вы также можете хранить как самое высокое частоту, так и самый часто используемый элемент.

Различные типы имеют разную эффективность для разных типов данных, конечно, но это будет худший случай только двух итераций.

Изменить: Извинения за повтор... "Не знаю, когда я начал:)

Ответ 5

int count = 1;
int currentIndex = 0;
for (int i = 1; i < A.Length; i++)
{
    if (A[i] == A[currentIndex])
        count++;
    else
        count--;
    if (count == 0)
    {
        currentIndex = i;
        count = 1;
    }
}

int mostFreq = A[currentIndex];

Ответ 6

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MostFrequentElement
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] array = new int[] { 4, 1, 1, 4, 2, 3, 4, 4, 1, 2, 4, 9, 3, 1, 1, 7, 7, 7, 7, 7 };
            Array.Sort(array, (a, b) => a.CompareTo(b));
            int counter = 1;
            int temp=0 ;

            List<int> LOCE = new List<int>();
            foreach (int i in array)
            {
                counter = 1;
                foreach (int j in array)

{
                    if (array[j] == array[i])
                    {
                        counter++;
                    }
                    else {
                    counter=1;
                    }
                    if (counter == temp)
                    {
                        LOCE.Add(array[i]);
                    }
                    if (counter > temp)
                    {
                        LOCE.Clear();
                        LOCE.Add(array[i]);
                        temp = counter;

                    }
                }

            }
            foreach (var element in LOCE)
            {
                Console.Write(element + ",");
            }
            Console.WriteLine();
            Console.WriteLine("(" + temp + " times)");
            Console.Read();
        }
    }
}

Ответ 7

Вот пример того, как вы могли бы сделать это без LINQ и без словарей и списков, всего два простых вложенных цикла:

public class MostFrequentNumber
{
    public static void Main()
    {
        int[] numbers = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();

        int counter = 0;
        int longestOccurance = 0;
        int mostFrequentNumber = 0;

        for (int i = 0; i < numbers.Length; i++)
        {
            counter = 0;

            for (int j = 0; j < numbers.Length; j++)
            {
                if (numbers[j] == numbers[i])
                {
                    counter++;
                }
            }

            if (counter > longestOccurance)
            {
                longestOccurance = counter;
                mostFrequentNumber = numbers[i];
            }
        }

        Console.WriteLine(mostFrequentNumber);
        //Console.WriteLine($"occured {longestOccurance} times");
    }
}

Вы получаете значение наиболее часто встречающегося числа, и (прокомментировал) вы могли бы получить также числа вхождений. Я знаю, что у меня есть "использование Linq", это просто для преобразования исходной строки ввода в массив int и для сохранения пары строк и цикла синтаксического анализа. Алгоритм хорош даже без него, если вы заполните массив "длинным" способом...