自己的解法
- 一個map記錄每個數字的頻率
- 最小堆保存這些數據,再用k依次去減,看能去掉多少
- 最終將map的大小減去去掉的數字即可得到答案
- 時間複雜度O(nlogn)
class Solution {
public:
int findLeastNumOfUniqueInts(vector<int>& arr, int k) {
unordered_map<int,int> mymap;
int len = arr.size();
for(int i=0; i<len; i++){
mymap[arr[i]]++;
}
unordered_map<int, int>::iterator iter;
priority_queue<int, vector<int>, greater<int>> minHeap;
for(iter=mymap.begin();iter!=mymap.end();iter++){
minHeap.push(iter->second);
}
int del = 0;
while(k-minHeap.top()>=0){
k-=minHeap.top();
minHeap.pop();
del++;
}
return mymap.size()-del;
}
};
時間複雜度爲O(n)的方法
- 依舊是map記錄每個元素的頻次。
- 比如原始數據[1,1,2,2,3,3,3],k=4
- 計算得到{1:2, 2:2, 3:3}
- 對這些頻次再用map記錄,即“頻次的頻次”
- 刪除元素的話,就直接按照所有可能的頻次,由低到高開始找,刪除。從最小的,即頻次爲1的元素開始刪除(先不管有沒有頻次爲1的)。然後一直到頻次最大的數字,即arr.size(可能也不存在),依次遍歷刪除即可。
- 還拿上面的例子,如果找到一個,比如頻次爲2,發現頻次2它的頻次也是2,即arr中有兩個數字的頻次都是2。
- k減去這兩個數x它們的頻次,即k-22,得到還可以減的量是4-22=0
- 總的數字種類也-2,即去掉了2不同的數,還剩{3,3,3}
- 再這樣循環下去,發現k不夠減了,則k整除當前頻次,看看能減多少減多少。舉另一個例子,與之前情況相同但k=3,那麼k=3減不了2*2,即去掉兩個不同的數,因此k可以減掉其中一個,即k//2=1(整除),具體代碼如下
def findLeastNumOfUniqueInts(self, arr: List[int], k: int) -> int:
c = Counter(arr)
cnt, remaining = Counter(c.values()), len(c)
for key in range(1, len(arr) + 1):
if k >= key * cnt[key]:
k -= key * cnt[key]
remaining -= cnt[key]
else:
return remaining - k // key
return remaining
參考
Leetcode Discuss