稀疏相似度
最爲樸素的做法:
文檔之間一一匹配,然後用一個set<int>
,記錄一下兩個文的並集,然後用原來的個數之和減去並集的個數即爲交集數。
時間複雜度:
class Solution {
public:
vector<string> ans;
vector<string> computeSimilarities(vector<vector<int>>& docs) {
for(int i=0;i<docs.size();i++){
for(int j=i+1;j<docs.size();j++){
unordered_set<int> s;
for(int x:docs[i]){
s.insert(x);
}
for(int x:docs[j]){
s.insert(x);
}
int sum = docs[i].size()+docs[j].size()-s.size();
if(sum){
char res[100];
sprintf(res,"%d,%d: %.4f",i,j, 1.0*sum/s.size()+ 1e-9 );
ans.push_back(res);
}
}
}
return ans;
}
};
如何優化呢?注意到題乾的稀疏二字,意思是有大量數字它們從頭至尾只出現了一次,但是爲了求出交集,我們卻不得不把這些只出現了一次的單詞也插入到set中。
所以,我們只需預處理一下某個數字在那些文檔裏出現過,
用unordered_map<int,vector<int>> word
,記錄,然後一個二維數組統計交集。
但要注意,在一般的數據下,這並不能起到優化效果。時間複雜度並沒有改變。
class Solution {
public:
vector<string> computeSimilarities(vector<vector<int>>& docs) {
vector<string> ans;
unordered_map<int,vector<int>> word;
int n = docs.size();
for(int i=0;i<n;i++){
for(int x:docs[i]){
word[x].push_back(i);
}
}
vector<vector<int>> count(n,vector<int>(n,0));
for(auto it:word){
vector<int> &ids = it.second;
for(int i=0;i<ids.size();i++){
for(int j=i+1;j<ids.size();j++){
count[ids[i]][ids[j]]++;
}
}
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(count[i][j]){
int bs = docs[i].size()+docs[j].size()-count[i][j];
char buf[100];
sprintf(buf,"%d,%d: %.4f",i,j,1.0*count[i][j]/bs + 1e-9);
ans.push_back(buf);
}
}
}
return ans;
}
};