[英]C#: O(n²) solution to finding n/k elements of an array of of size n and a number k
我正在嘗試使用 O(n²) 解決方案來查找給定數組中哪些元素出現次數超過 n/k 次(在這種情況下 n=8 - 超過兩次)。 我相信我有解決方案,但我似乎無法弄清楚為什么輸出(如下所示)不是 [2, 3]。 我知道它出現在索引 i = 3 處的元素 2,但我認為if (count > (arr.Length / k))
條件會解決這個問題。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4, count = 1;
for(int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (arr.Length / k))
{
Console.WriteLine(arr[i] + " " + i);
count = 1;
}
}
}
}
輸出:
3 0
2 2
2 3
問題是您僅在匹配且count
大於arr.Length/k
時才重置count
。 您需要在內部for
循環結束時重置它,或者更好地在內部for
循環之前定義它for
因為在該循環之外不需要它。 此外,我猜您會希望在count
滿足您的條件后立即中斷該循環,否則您將繼續寫出相同的內容。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
for(int i = 0; i < arr.Length; i++)
{
int count = 1;
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (arr.Length / k))
{
Console.WriteLine(arr[i] + " " + i );
break;
}
}
}
}
但是,這仍然會為其他位置的重復值產生結果。 例如數組 {3, 1, 2, 2, 1, 2, 3, 3, 3, 3, 3, 3} k 等於 4 產生 3,0; 3,6; 3,7; 和 3,8。 假設您只想要 3,0,那么更好的解決方案是。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
var results = arr.Select((x,i) => new {Value = x, Index = i})
.GroupBy(x => x.Value)
.Where(grp => grp.Count() > arr.Length / k)
.Select(grp => grp.First());
foreach(var r in results)
{
Console.WriteLine($"{r.Value} {r.Index}");
}
或者,如果您更喜歡使用for
循環而不是 Linq,那么您只需要一個HashSet<int>
來跟蹤您已經看到的值。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
HashSet<int> seen = new HashSet<int>();
for(int i = 0; i < arr.Length; i++)
{
if(!seen.Add(arr[i]))
{
continue;
}
int count = 1;
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (arr.Length / k))
{
Console.WriteLine(arr[i] + " " + i );
break;
}
}
}
}
請注意,當值已經在哈希集中時, Add
返回 false。
這不是最優化的方式嗎? 因為您不想檢查最后一個arr.Length/k
元素,因為如果所有元素都相同,那么它們只會是are.Length/k
而不是> are.Length/k
in Quantity
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
int target = arr.Length/k;
for(int i = 0; i < arr.Length - target; i++)
{
int count = 1;
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (target))
{
Console.WriteLine(arr[i] + " " + i );
break;
}
}
}
}
如果您可以使用算法對O(n log n)
或更少進行排序,那么這樣的事情可能會有用:
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int[] sorted = Sort(arr); //sort method
int k = 4;
int target = arr.Length/k;
int count = 0;
for(int i = 0; i < arr.Length - target; i++)
{
count++;
if(arr[i] != arr[i+1])
{
if(count > target)
Console.WriteLine($"{arr[i]} {count}");
count = 0;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.