给定多个集合,如何找到每个集合中所有其他子集唯一的最小子集?

问题描述

背景。我的数字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(' '))