簡體   English   中英

計算數組中的不同值-C ++

[英]Count distinct values in an array - C++

我正在嘗試自學(重新學習)C ++,並通過網上書籍和測試來解決問題,以獲得一些練習。 我遇到了這個問題,這讓我有些困惑。 我最好怎么做?

我必須寫一個函數

class Solution { public int distinct (int [] A); }

返回數組A中不同值的數量。我可以假定數組范圍是0到100,000。 元素都是+或-1,000,000的整數。 有任何想法嗎? 我當時想遍歷並計算每個值,但這可能效率很低,對吧? 提前致謝。

編輯更新:包括一個優化空間的算法,只是為了好玩

您可以使用std :: set包含唯一值。 只需將數組元素復制到集合中(無論如何),然后計算集合中唯一元素的數量。

這是一個相當簡潔的代碼,甚至不需要您指定數組的大小(盡管,通常在c ++中,您仍然會使用std::vector ):

http://ideone.com/rpWGS上實時查看 (包含測試數據和輸出)

#include <set>

class Solution 
{ 
   public: 

     // using std::set (max O(n) additional storage)
     template<size_t N>
         static size_t distinct (int (&a)[N])
     {
         return std::set<int>(a, a+N).size();
     }

     // using std::unique (inplace mutation; no additional storage)
     template<size_t N> 
         static size_t distinct_optim(int (&a)[N])
     {
         std::sort(a, a+N);
         int* newend = std::unique(a, a+N);
         return newend - a; 
     }

};

您的解決方案相當有效(實際上,就時間復雜度而言,效率最高),但是在空間上,要計算值,您需要一個大小為可能值范圍的數組,以便計算實例在100,000個項目的數組中,您需要〜2,000,000個項目的輔助數組(覆蓋范圍從-1,000,000到1,000,000)。

您有幾種方法可以避免/減少這種情況。 一種是僅為每個可能的輸入存儲一位,然后在看到該輸入時將其設置。 這具有相同的基本復雜度 ,但是將計數的空間減少到最低限度(即,您實際上並不關心任何輸入發生了多少次,只關心是否發生了輸入)。 在C ++中,實現此目的的明顯方法是std::vector<bool> 盡管經常被破壞,在這種情況下, vector<bool>確實可以滿足您的需求。

另一種可能性是使用從輸入數字到計數/位的稀疏映射。 尤其是當您的范圍遠大於輸入的數量時,這可以節省很多空間(占用的空間將與輸入的數量成比例,而不是范圍)。 在C ++中,實現此目的的明顯方法是std::set<int> 為了保持相同的預期復雜度(O(N)而不是O(N log N),您想使用unordered_set

另一種可能性是對輸入進行排序,然后消除重復項。 這通常將輔助存儲保持在最低水平,但是通常需要稍長的時間才能執行(O(N log N)而不是O(N))。 為此,您可能會使用std::vectorstd::sortstd::unique

對數組A進行排序。然后遍歷排序后的數組,並計算兩個連續數字之間的差為非零的次數。 確保照顧好陣列的邊緣以及陣列大小為1的情況。

我可以想到兩種選擇:

1)使用快速排序或合並排序對向量進行排序,然后遍歷排序后的向量,每次遇到與當前值不同的值時就進行計數。

2)設置大小為1,000,000的std::vector<bool>並在迭代數組時放入true值。 之后,您計算true值的數量。 我說vector<bool>是因為它針對高效存儲進行了優化,即它可能在一個字節中存儲8個vector<bool>

要獲得數組中不同值的數量,我可以看到兩種可能性。

首先是對它們進行排序,然后計算轉換的數量(加一個)。 例如,以下列表:

1 1 1 1 2 2 3 4 4 5
       ^   ^ ^   ^

有四個轉換,因此有五個不同的值。

另一種可能性是設置一個“布爾值”數組,該數組指示是否曾經看過一個數字,例如(在您的情況下)偽代碼:

def countDistinct (array):
    def notSeenYet[-1,000,000..1,000,000] as all true
    count = 0
    for each value in array:
        if notSeenYet[value]:
            notSeenYet[value] = false
            count = count + 1
    return count

第一個要求排序的時間復雜度最多為O(n log n)。 對於100,000個元素來說,這不太可能是一個嚴重的問題,但是您可能不希望以任何方式修改數組(這將需要副本,空間復雜度為O(n))。

第二個是O(n)時間復雜度和您的情況的恆定存儲。 取決於您的環境, 可能需要考慮200萬個布爾值,但是如果時間允許,則最好(通常是這樣),如果可能的話,這樣做會更好。

暫無
暫無

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

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