数组中出现频率最高的数字

12

我有一个数组,编写了一个函数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);
}

@Brandon 你正在使用哪个版本的C#? - Nathan W
我刚刚编辑了标签,以便人们知道要瞄准哪个版本。 - Nathan W
数据集中出现频率最高的数字被称为模式。因此,也许在命名你的方法时使用GetArrayMode()或类似的内容会很有用。 - mmcdole
11个回答

9
LINQ起来。我知道这是VB语言,但你应该可以将其转换为C#:
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}

编辑:现在也有C#版本了:

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

7
假设您不能使用LINQ,我可能会这样处理该算法:
  • 创建键值字典
  • 遍历数组,在字典中为每个唯一元素添加一个键,每次重复该元素时增加值。
  • 遍历字典键,并返回具有最高值的元素。
这不是一个很好的解决方案,但它很简单,ContainsKey是一个O(1)查找,因此最多迭代两次数组。

3

从软件工程的角度来看,我希望一个名为MostFreq的函数返回最高频率的元素,而不是频率本身。我会交换你的输出和返回值。


2
您可以通过在整个数组上进行迭代,使用临时数组记录每个值出现的次数,然后在临时数组上进行迭代以获取最高次数,来消除您在开头执行的排序。您还可以始终保留最高频率计数和最常见项目。当然,不同类型的数据有不同的效率,但这将是最坏情况下仅需两次迭代的解决方案。
编辑:很抱歉重复了... 我开始时没有看到 :)

1

一次通过完成....

public class PopularNumber
    {
        private Int32[] numbers = {5, 4, 3, 32, 6, 6, 3, 3, 2, 2, 31, 1, 32, 4, 3, 4, 5, 6};

        public PopularNumber()
        {
            Dictionary<Int32,Int32> bucket = new Dictionary<Int32,Int32>();
            Int32 maxInt = Int32.MinValue;
            Int32 maxCount = 0;
            Int32 count;

            foreach (var i in numbers)
            {
                if (bucket.TryGetValue(i, out count))
                {
                    count++;
                    bucket[i] = count;
                }
                else
                {
                    count = 1;
                    bucket.Add(i,count);
                }

                if (count >= maxCount)
                {
                    maxInt = i;
                    maxCount = count;
                }

            }

            Console.WriteLine("{0},{1}",maxCount, maxInt);

        }
    }

0
int[] numbers = new int[] {1, 2, 3, 2, 1, 4, 2};

Dictionary<int, int> numberCounts = new Dictionary<int, int>();

foreach (int number in numbers)
{
    if (numberCounts.ContainsKey(number))
    {
        numberCounts[number]++;
    }
    else
    {
        numberCounts[number] = 1;
    }
}

int maxCount = numberCounts.Values.Max();
int mostFrequentNumber = numberCounts.Where(x => x.Value == maxCount).OrderByDescending(x => x.Key).First().Key;

Console.WriteLine("Most frequent number: " + mostFrequentNumber);

目前你的回答不够清晰,请[编辑]以添加更多细节,帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0
int[] arr = { 4, 5, 6, 4, 4, 3, 5, 3 };
var gr = arr.GroupBy(x => x).OrderBy(x => x.Count()).Last();
Console.WriteLine($"The most Frequent Item = {gr.Key} with frequency = {gr.Count()}"); // The most Frequent Item = 4 with frequency = 3

2
仅仅提供代码片段而没有任何解释很少有帮助。Stack Overflow 是关于学习的,而不是提供盲目复制粘贴的片段。请编辑您的问题并解释它如何回答特定的问题。参见 [答案]。当回答旧问题(这个问题已经接近12.5年了)时,尤其重要的是要考虑现有答案(已经有12个其他答案)。这个答案如何改进已经存在的内容? - Chris

0

这是一个例子,演示如何在没有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");
    }
}

您可以获取最常出现的数字的值,以及(已注释)出现次数的数字。我知道我有一个“using Linq;”,那只是为了将初始输入字符串转换为int数组,并节省几行代码和解析循环。即使不使用它,算法也是正确的,如果您用“长”的方式填充数组...


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

0
假设数组如下:

int arr[] = {10, 20, 10, 20, 30, 20, 20,40,40,50,15,15,15};

int max = 0;
int result = 0;
Map<Integer,Integer> map = new HashMap<>();

for (int i = 0; i < arr.length; i++) {
    if (map.containsKey(arr[i])) 
        map.put(arr[i], map.get(arr[i]) + 1);
    else
        map.put(arr[i], 1);
    int key = map.keySet().iterator().next();
    if (map.get(key) > max) {
        max = map.get(key) ;
        result = key;
    }
}
System.out.println(result);

解释:

在上面的代码中,我使用了HashMap来存储元素作为键和元素重复次数作为值。我们初始化变量max = 0(max是重复元素的最大计数)。在迭代元素时,我们还获取键的最大计数。

结果变量返回具有最多重复的键。


看起来你拿去了我五月份写的代码,从C#翻译成了C++。 这让我想起一个笑话。C++和C#哪个更快? 大约一个月的时间,C#更快... - AnthonyLambert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接