【LeetCode】每日一题 面试题 17.26. 稀疏相似度

167 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

[面试题 17.26. 稀疏相似度](leetcode.cn/problems/ma…)

两个(具有不同单词的)文档的交集(intersection)中元素的个数除以并集(union)中元素的个数,就是这两个文档的相似度。例如,{1, 5, 3} 和 {1, 7, 2, 3} 的相似度是 0.4,其中,交集的元素有 2 个,并集的元素有 5 个。给定一系列的长篇文档,每个文档元素各不相同,并与一个 ID 相关联。它们的相似度非常“稀疏”,也就是说任选 2 个文档,相似度都很接近 0。请设计一个算法返回每对文档的 ID 及其相似度。只需输出相似度大于 0 的组合。请忽略空文档。为简单起见,可以假定每个文档由一个含有不同整数的数组表示。

输入为一个二维数组 docs,docs[i] 表示 id 为 i 的文档。返回一个数组,其中每个元素是一个字符串,代表每对相似度大于 0 的文档,其格式为 {id1},{id2}: {similarity},其中 id1 为两个文档中较小的 id,similarity 为相似度,精确到小数点后 4 位。以任意顺序返回数组均可。

「示例1:」
输入: 
[  [14, 15, 100, 9, 3],
  [32, 1, 9, 3, 5],
  [15, 29, 2, 6, 8, 7],
  [7, 10]
]
输出:
"0,1: 0.2500""0,2: 0.1000""2,3: 0.1429"]
「提示:」
docs.length <= 500
docs[i].length <= 500

解题思路

无~

代码实现

/**
 * @param {number[][]} docs
 * @return {string[]}
 */
const extra = 10 ** -9
var computeSimilarities = function(docs) {
    const len = docs.length
    const map = new Map()
    for(let i = 0; i < len; i++) {
        for(let num of docs[i]) {
            if(map.has(num)) {
                map.get(num).push(i)
            } else map.set(num, [i])
        }
    }
    const resMap = new Map()
    for(let entry of map) {
        const list = entry[1]
        if(list.length < 2) continue
        for(let i = 0; i < list.length; i++) {
            for(let j = i + 1; j < list.length; j++) {
                const newPair = list[i] + ',' + list[j]
                if(resMap.has(newPair)) {
                    resMap.set(newPair, resMap.get(newPair) + 1)
                } else resMap.set(newPair, 1)
            }
        }
    }
    const ans = []
    for(let entry of resMap) {
        const pair = entry[0].split(',')
        const diff = docs[pair[0]].length + docs[pair[1]].length - entry[1]
        ans.push(entry[0] + ': ' + ((entry[1] / diff) + extra).toFixed(4))
    }
    return ans
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;