[英]How to count the number of distinct values in a C++ std::map<Key,Values>
[英]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::vector
, std::sort
和std::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.