【发布时间】:2018-09-29 14:35:41
【问题描述】:
所以我试图找出一个算法来搜索一个数组,只需一次通过即可找到其中出现的最频繁的数字。我尝试使用两个内部循环来解决它并且它可以工作,但这需要多次循环遍历数组。
现在,我正试图通过一次“扫描”数组来找到最常见的数字来找出另一种方法。有人有什么建议可以帮助吗?
【问题讨论】:
所以我试图找出一个算法来搜索一个数组,只需一次通过即可找到其中出现的最频繁的数字。我尝试使用两个内部循环来解决它并且它可以工作,但这需要多次循环遍历数组。
现在,我正试图通过一次“扫描”数组来找到最常见的数字来找出另一种方法。有人有什么建议可以帮助吗?
【问题讨论】:
使用 LINQ,您可以简单地使用,
var mostfrequent = myList.GroupBy(i=>i).OrderByDescending(grp=>grp.Count())
.Select(grp=>grp.Key).First();
编辑
根据OP对Hashtable的要求,可以如下实现,
int mostCommom = array[0];
int occurences = 0;
foreach (int num in array)
{
if (!hs.ContainsKey(num))
{
hs.Add(num, 1);
}
else
{
int tempOccurences = (int)hs[num];
tempOccurences++;
hs.Remove(num);
hs.Add(num, tempOccurences);
if (occurences < tempOccurences)
{
occurences = tempOccurences;
mostCommom = num;
}
}
}
foreach (DictionaryEntry entry in hs)
{
Console.WriteLine("{0}, {1}", entry.Key, entry.Value);
}
Console.WriteLine("The commmon numer is " + mostCommom + " And it appears " + occurences + " times");
【讨论】:
您可以使用字典并将键设置为数字,然后当您遇到一个您已经遇到的数字时,将当前数字的值(即键)加 1,当数组完成时,用最高值。
【讨论】:
这样的事情应该可以工作(您需要获取 ValueTuple NuGet 包才能使该元组调用签名工作):
public static IEnumerable<int> ListOfInts = new List<int> { 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5 };
public static (int? mostFrequent, int numOccurances) FindMostFrequent(IEnumerable<int> ints) {
int maxNumOccurances = int.MinValue;
int? mostFrequent = null;
//key is number (that occurs), value is number of occurances
var counters = new Dictionary<int, int>();
foreach (var num in ints) {
if (counters.TryGetValue(num, out var occurances)) {
counters[num] = ++occurances;
} else {
counters[num] = 1;
}
if (occurances > maxNumOccurances) {
mostFrequent = num;
maxNumOccurances = occurances;
}
}
return (mostFrequent, maxNumOccurances);
}
它遍历整数集合一次。它在遍历列表时构建一个Dictionary<int, int>,执行 N 次查找和 N 次写入(插入或替换)。
如果列表为空,则返回的mostFrequent 部分将为null。如果最大值出现不止一次,您将得到第一个找到的。如果您想要最后一个,请将> 更改为>= in:
if (occurances > maxNumOccurances)
并且,如果您想要所有可能的结果,请在返回之前执行以下操作:
var maxes = from pair in counters where pair.Value == maxNumOccurances select pair;
【讨论】: