簡體   English   中英

查找數組在小於O(n ^ 2)內重復的次數

[英]Find the number of times a number is repeated in an array in less than O(n^2)

我寫的示例代碼。但這是n ^ 2

int a[]={1,4,1,5,2,2,4,3,4,1};
int b[][]=new int[5][2];
int i,j,k=0,count=1;
boolean temp=false;
for(i=0;i<a.length;i++)
{
    for(j=0;j<5;j++)
    {
        if(a[i]==b[j][0])
        {   temp=true;
            b[j][1]++;
            break;
        }
    }

    if(temp==false)
    {
        b[k][0]=a[i];
        b[k][1]=1;
        k++;    
    }
    temp=false;
}
for(i=0;i<5;i++)
{
    for(j=0;j<1;j++)
    {
    System.out.println(b[i][j]+" is repeated "+b[i][j+1]+" times");
    }
}

這是偽代碼的解決方案:

Map<Int, Int> histogram;
for(number in array) {
    histogram[number]++;
}

現在histogram[somenumber]包含數字在數組中的次數 - 在O(n)假設MapO(1)查找項目

選項1:犧牲記憶速度。

  • 使用像HashMap這樣的數據結構來記錄每個數字的頻率。
  • 在O(n)時間內迭代以構建頻率計數,然后迭代整個HashMap或提取一個值。

選項2:排序

  • 排序,然后迭代整個排序結構或O(log n)以尋找特定值。
    • Quicksort具有平均n log n,O(n ^ 2)最壞情況,就地存儲器。
    • Mergesort或heapsort是O(n log n)但在排序期間占用額外的內存

偽代碼:

counts = dictionary default to 0

for each element in list:
    counts[element]+=1

上)

你應該使用eg。 合並排序以對數組進行排序,然后使用簡單的for循環遍歷整個數組來計算重復次數。

合並排序有n * log(n),而for循環查找重復也很快。

快速排序算法應該比O(n ^ 2)快得多,然后是一個組,即O(n)應該仍然比O(n ^ 2)快。

因此,在偽代碼中:

    group (sort [1,2,3,3,2,1])   =>   [(1,2), (2,2), (3,2)] 

您可以通過創建另一個數據結構(如地圖)在O(n)時間內完成。 例如:int a [] = {1,4,1,5,2,2,4,3,4,1};

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

for(int i = 0; i < a.length ; i++)
{
    if(map.containsKey(a[i]))
    {
        map.put(a[i], map.get(a[i])+1);
    }
    else
    {
        map.put(a[i], 1);
    }
}

System.out.print(map);

結果:{1 = 3,2 = 2,3 = 1,4 = 3,5 = 1}

為什么使用2-dim陣列? 如果已知您的數字在1..5范圍內,請使用該數字的索引:

    int a[] = {1,4,1,5,2,2,4,3,4,1};
    int b[] = new int[5];

    for (int n : a)
        ++b[n-1];

    for (int j=0; j < 5; ++j)
        System.out.println (j + " is repeated " + b [j-1] + " times");
  • 不要聲明變量過早,也不要重復使用它們。 您將忘記刪除未使用的變量(計數),並難以分析代碼。
  • 使用改進的for:loop。
  • 在頭部聲明計數器 - 這是允許的原因:for(int i = ...)以及為什么我在塊外不可見。 它不貴。 不,不是。 看一下字節碼。

如果您可以更改現有陣列,則可以執行此操作。 它的O(n log(n))並不會創建新對象。 (如果你無法改變原作,你可以克隆它。)它比維護Map更有效。 ;)

int a[] = {1, 4, 1, 5, 2, 2, 4, 3, 4, 1};

Arrays.sort(a);
int last = a[0];
int count = -1; 
for (int i : a) {
    if (i == last) {
        count++;
        continue;
    }
    System.out.println("Number " + last + " found " + count + " times.");
    count = 1;
    last = i;
}
System.out.println("Number " + last + " found " + count + " times.");

版畫

Number 1 found 3 times.
Number 2 found 2 times.
Number 3 found 1 times.
Number 4 found 3 times.
Number 5 found 1 times.

在這種情況下,將O(n ^ 2)減少到O(n * log n)很簡單:

  1. 使用heapsort / quicksort對數字進行排序... O(n * log n)
  2. 遍歷數組一次並計算唯一元素並得到它們的計數...... O(n)

保持一個高度平衡的樹,數字作為鍵以及出現次數是另一個想法,它將給出O(n * log n)。 我沒有看到O(n)解決方案沒有使用大多數語言中容易獲得的數據結構的散列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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