[英]What is the fastest way to find Nth biggest number of an INT array?
我想要一個更快的函數來查找 C# 中 Int 數組的第 N 個最大數。 此函數接受 N 和 Array 並返回該數字的索引。
這是我已經擁有的。 它只是對數組進行排序,然后返回該數字的索引。 它工作得很好,但我不確定這是否是最快的方法。 沒有完全排序的算法似乎是合乎邏輯的。
static int myFunction(int[] array, int N){
int[] indexes = new int[array.Length];
for (int i = 0; i < indexes.Length; i++)
indexes[i] = i;
for (int i = 0; i < array.Length; i++)
{
for (int j = i + 1; j < array.Length; j++)
{
if (array[i] < array[j])
{
int m = array[j];
array[j] = array[i];
array[i] = m;
m = indexes[j];
indexes[j] = indexes[i];
indexes[i] = m;
}
}
}
return indexes[N];
}
一些結果:
myFunction(new int[] { 1, 3, 2, 0, 10 }, 0); //returns 4 (index of 10)
myFunction(new int[] { 1, 3, 2, 0, 10 }, 1); //returns 1 (index of 3)
myFunction(new int[] { 1, 3, 2, 0, 10 }, 2); //returns 2 (index of 2)
隨機快速選擇算法在平均案例復雜度 O(n) 下工作。 實際上,O(n^2) 是非常罕見的。 它使用快速排序的分區功能
如果您的數組有無數個數字,而您需要第五大數字,那么您正在對很多不需要的數字進行排序。
保持長度為 n 的升序排序序列(鏈表?)是否會更快,並且對於每個元素檢查它是否大於第一個(升序中最小的元素)
掃描完整數組后,排序序列中的第一個元素就是您要查找的元素。
大多數比較僅與排序數組的第一個元素進行。 您必須更改數組 N 次,一次更改 N 個最大的數字。 數組的一個變化是移除第一個元素(最小的)並找到插入新元素的地方以保持數組排序
更正:我關於數組必須更改 N 次的說法是不正確的。 這在提供按升序排序的數組時最容易看出:每個比較的數字都將大於 N 大小數組中的最小數字,從而導致替換
這將是@HaraldDutch 答案的實現。
int get(int[] array, int n)
{
var comparer = Comparer<int>.Create((x, y) => array[x].CompareTo(array[y])); //compare the array entries, not the indices
var highestIndices = new SortedSet<int>(comparer);
for (var i = 0; i < array.Length; i++)
{
var entry = array[i];
if (highestIndices.Count < n) highestIndices.Add(i);
else if (array[highestIndices.Min] < entry)
{
highestIndices.Remove(highestIndices.Min);
highestIndices.Add(i);
}
}
return highestIndices.Min;
}
不過,您必須傳入 1 而不是 0。
你需要使用選擇算法https://en.wikipedia.org/wiki/Selection_algorithm
這里有不錯的幻燈片: https ://c3p0demo.googlecode.com/svn/trunk/scalaDemo/script/Order_statistics.ppt 一般算法:
Select(A,n,i):
Divide input into ⌈n/5⌉ groups of size 5.
/* Partition on median-of-medians */
medians = array of each group’s median.
pivot = Select(medians, ⌈n/5⌉, ⌈n/10⌉)
Left Array L and Right Array G = partition(A, pivot)
/* Find ith element in L, pivot, or G */
k = |L| + 1
If i = k, return pivot
If i < k, return Select(L, k-1, i)
If i > k, return Select(G, n-k, i-k)
你可以創建一個大小為 N 的堆,它的第一個元素是最大的(而不是通常給出的最小的)。 然后遍歷整數數組,只要有一個元素小於堆的最大成員,就將其插入堆中。 如果這使得堆超過 N 的大小,則刪除其中最大的成員。
這應該是最便宜的方法之一。 特定的“m 中第 n 大”算法可能會擊敗它,但可能不會漸近。
您的排序算法目前還不是最快的。 您應該在谷歌上搜索“Quicksort”以獲得更快的算法。
而當你實現了快速排序之后,你就會考慮是否真的需要對整個數組進行排序。 假設你要從 10,000 個數字中找出最大的 20 個,為什么要對剩余的 9,980 個數字進行排序? 您可以輕松修改 Quicksort,使其找到 N 個最大的數字,但大部分忽略其余數字。
也許這可以幫助某人。 在 int 數組中找到第 n 個最大的數字。
int[] arr = new int[] { 3, 2, 1, 5 };
Array.Sort(arr);
int elemCount = 0;
int? thirdLargestNumber = null;
foreach (var elem in arr)
{
var temp = arr.Skip(elemCount).ToArray();
if (temp.Length == 3) //replace `3` with variable.
{
thirdLargestNumber = temp[0];
break;
}
elemCount++;
}
Console.WriteLine($"Third largest number = {thirdLargestNumber}");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.