chenfy27的刷题记录

导航

leetcode 面试17.26 稀疏相似度

一个文档可以用某个int集合来表示,两个文档的相似度定义为对应集合的交集大小除以并集大小,例如{1,5,3}与{1,7,2,3}的相似度为0.4。给定n个相似度很稀疏的文档,返回所有相似度大于0的组合。
1<=n<=500, 1<=set[i]<=500

分析:采用类似倒排索引的做法,对集合中的每个int,记录在哪些文档中出现过,然后遍历每个int,对包含该int的文档的两两组成的pair,其交集数加1。最后遍历所有pair统计结果即可。由于题目限定稀疏相似度,pair数很少,时间复度度为O(n^2)。

class Solution {
public:
    vector<string> computeSimilarities(vector<vector<int>>& docs) {
        int n = docs.size();
        std::map<int,std::vector<int>> mp;
        for (int i = 0; i < n; i++) {
            for (auto u : docs[i]) {
                mp[u].push_back(i);
            }
        }
        std::map<std::pair<int,int>,int> cnt;
        for (auto &[k,v] : mp) {
            int m = v.size();
            for (int i = 0; i < m; i++) {
                for (int j = i + 1; j < m; j++) {
                    std::pair<int,int> pr = {v[i], v[j]};
                    cnt[pr] += 1;
                }
            }
        }
        char buf[32];
        std::vector<std::string> ans;
        for (auto &[pr,v] : cnt) {
            int A = v;
            int B = docs[pr.first].size() + docs[pr.second].size() - A;
            sprintf(buf, "%d,%d: %.4f", pr.first, pr.second, 1E-9 + 1.0 * A / B);
            ans.push_back(buf);
        }
        return ans;
    }
};

注意,这里可能会有精度问题,例如,1/32的准确值为0.03125,由于计算机表示精度的问题,实际保存的值可能是0.0312499999或者0.03125000001等,如果是前者,输出结果就是0.0312,导致错误,因此要加eps。
eps取大了也不行,比如1/59的近似值为0.016949152,如果eps取1E-6,就是0.016950152,导致答案不对,一般取eps=1E-9。

posted on 2024-12-03 22:50  chenfy27  阅读(5)  评论(0编辑  收藏  举报