稀疏相似度
最为朴素的做法:
文档之间一一匹配,然后用一个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;
}
};