我在C#中有一个int数组,我希望获得整个数组的5%,就像新数组包含最常见的相似值一样。 举个例子,假设我有一个包含100个条目的数组,其中包含40个兄弟姐妹20(15到25)。我想要的是将20作为最常见的值(包括它的兄弟)检测为新数组,然后检测新数组中最常见的5个值。 我需要在ASP.net网站上运行代码,因此,我需要一个快速的算法。 有人可以帮我这个吗?
答案 0 :(得分:3)
您可以通过对值进行分组,按计数排序,然后获取它们直到填充所需的5%数组来构建一个简单的算法,如下所示:
// Build a set of {Value, Count} pairs using LINQ
var counts = data
.GroupBy(v => v)
.Select(g => new {
Value = g => Key
, Count = g.Count()
}).OrderByDescending(p => p.Count)
.Take(5);
编辑:
阵列大小可能大到1024 * 1024,范围介于0到255之间
由于范围非常小,您可以使用计数数组而不是组,如下所示:
int counts = new int[256];
foreach (var b in data) {
counts[b]++;
}
现在您可以运行Quick Select Algorithm来选择第五项。以下an answer提供了QuickSelect
的C#实现。
var fifth = QuickSelect(counts, 5);
var res = new List<KeyValuePair<int,int>>();
for (int i = 0 ; i != counts.Length && res.Length != 5 ; i++) {
if (counts[i] >= fifth) {
res.Add(new KeyValuePair<int,int>(i, counts[i]));
}
}
您可能希望将快速选择算法替换为具有相同线性性能但未随机化的median-of-medians algorithm。
答案 1 :(得分:2)
var numbersByOccurrence = from numbers in yourNumberArrayVariable
group numbers by numbers into g
select new { Number = g.Key, Count = g.Count() };
var limitedSize = numbersByOccurrence.OrderByDescending(n => n.Count).Take(5);
现在你有一个5个对象的变量(你可以作为一个数组或列表进行转换),你可以轻松访问一个Number和Count变量。