问题描述
背景。我的数字1到20(黑色背景上的白色数字)可以显示在屏幕上,我希望识别这些数字。由于不能简单地复制粘贴它们,因此我将比较屏幕上该数字的白色像素的位置与所有20个数字的白色像素的位置的列表。但是,每个数字都可以具有大量像素,因此比较所有这些像素可能不需要标识该数字。因此,我想进行尽可能少的比较。
算法问题:我有多个集合,每个集合中的元素都是唯一的,但在所有集合中可能不是唯一的。如何找到每个集合的最小子集,以使每个子集都是唯一的?
示例1:令A = {1,2},而B = {3,4}。 A和B的最小子集为{1}和{3}(或{2}和{4}),因为这些子集对于每个原始集合都是唯一的,并且要尽可能小。
示例2:设A = {1,2,3,4},B = {1,5},C = {1,4,5}。可能的最小子集为{3,4},{3,5},{4,5}。如果从任何这些子集中删除了任何元素,则该子集也可以属于不同的集合。例如。从第一个子集中删除4将留下{3},如果{3}标识了第一组或第二组,则模棱两可。
解决方法
这是一个O(n ^ 3)时间复杂度和O(n)内存复杂度的解决方案。 (如果我没记错的话)
function isElement(elem,s) {
return s.includes(elem)
}
function isId(id,sets) {
let setsWithSuchElementsNumber = 0
for (const s of sets) {
if (id.every((e) => isElement(e,s))) {
setsWithSuchElementsNumber++
}
}
return setsWithSuchElementsNumber === 1
}
function getSetId(s,sets) {
const count = {}
const elements = []
for (const elem of s) {
if (count[elem] == null) {
elements.push(elem)
}
count[elem] = 0
}
for (const otherSet of sets) {
for (const e of elements) {
if (isElement(e,otherSet)) {
count[e]++
}
}
}
elements.sort((first,second) => {
return Math.sign(count[first] - count[second])
})
for (let idSize = 1; idSize <= elements.length; idSize++) {
const possibleId = elements.slice(0,idSize)
if (isId(possibleId,sets)) {
return possibleId
}
}
return null
}
const getSetIds = (sets) => {
return sets.map((s) => getSetId(s,sets))
}
const res = getSetIds([
[1,2,3,4],[1,5],4,])
console.log(res.join(' '))