簡體   English   中英

C#:O(n²) 解決方案,用於查找大小為 n 且數字為 k 的數組的 n/k 個元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM