首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >寻找最优的阵列交叉口

寻找最优的阵列交叉口
EN

Stack Overflow用户
提问于 2017-04-15 17:08:03
回答 2查看 77关注 0票数 0

我有一个数组和一个匹配的数组。每个数组都有唯一的id值。

MatchingArray = 1,2,3,4,5,6

A1 = 1,4,6

A2 = 2,3,5

A3 = 1,5

A4 =4

A5 = 1,6

需要找到“最佳匹配”。最优匹配是从A1到A5的子集数组,其长度最小,应该与MatchingArray有一个最大的可能交集。

在这个例子中,有两个可能的最大交集匹配: M1 = [2,3,5,1,4,6]和M2 = [ 1,5,4,1,6]。但是M1长度

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-15 20:32:26

您可以使用集合(或散列,无论语言如何称呼它们)来优化时间效率。

将目标数组转换为集合,然后从其中减去选定的源(即删除公共值)。继续递归地执行此操作,直到目标集为空。跟踪最佳结果(尽可能使用最少的源代码数组)。回溯,如果所使用的源数组的数量超过了此时已经找到的最佳解决方案的长度。

下面是Python中的代码:

代码语言:javascript
复制
def find_optimal_coverage(target, sources):
    max_size = len(target)
    best = None

    def recurse(target, sources, selected):
        nonlocal max_size, best
        if len(target) == 0:
            best = selected
            max_size = len(best) - 1
            return True
        if len(selected) == max_size:
            return None
        for i, source in enumerate(sources):
            result = recurse(target - set(source), sources[i+1:], 
                             selected + [list(source)])
            if result:
                return True

    target = set(target) # convert to set for faster lookup
    # limit the source lists to elements that occur in the target
    sources = list(map(target.intersection, sources))
    # limit target to elements that occur in at least one source
    target = set.union(*sources)
    # sort sources by decreasing length to maximise probability of 
    # finding optimal solution sooner
    sources.sort(key = len, reverse = True)
    if recurse(target, sources, []):
        return best

result = find_optimal_coverage(
    [1, 2, 3, 4, 5, 6, 8], 
    [
        [1, 4, 6, 7],
        [2, 3, 5],
        [1, 5],
        [4],
        [1, 6]
    ]
)
print(result)

看到它在repl.it上运行

在JavaScript中:

代码语言:javascript
复制
function subtractArray(s, arr) {
    return arr.reduce( (s, v) => (s.delete(v), s), new Set(s) );
}

function findOptimalCoverage(target, sources) {
    var maxSize = target.size;
    var best = null;
    
    function recurse(target, sources, selected) {
        if (target.size == 0) {
            best = selected;
            maxSize = best.length - 1;
            return true;
        }
        if (selected.length == maxSize) return;
        return sources.some( (source, i) =>
            recurse(subtractArray(target, source), sources.slice(i+1), 
                    selected.concat([source]))
        );
    }
    target = new Set(target) // convert to set for faster lookup
    // limit the source arrays to elements that occur in the target
    sources = sources.map( source => source.filter(target.has.bind(target)));
    // limit target to elements that occur in at least one source
    target = new Set([].concat(...sources)); 
    // sort sources by decreasing length to maximise probability of 
    // finding optimal solution sooner
    sources.sort( (a,b) => b.length - a.length );
    if (recurse(target, sources, [])) return best;
}

var result = findOptimalCoverage(
    [1, 2, 3, 4, 5, 6, 8], 
    [
        [1, 4, 6, 7],
        [2, 3, 5],
        [1, 5],
        [4],
        [1, 6]
    ]
);
console.log(result);
代码语言:javascript
复制
.as-console-wrapper { max-height: 100% !important; top: 0; }

票数 1
EN

Stack Overflow用户

发布于 2017-04-15 17:21:56

在javascript中实现的算法:

代码语言:javascript
复制
var matchingArray = [1, 2, 3, 4, 5, 6];

var A1 = [1, 4, 6],
  A2 = [2, 3, 5],
  A3 = [1, 5],
  A4 = [4],
  A5 = [1, 6];


var M = [A1, A2, A3, A4, A5];

function compareArrays(M, machingArray) {
  var intersections = []
  M.forEach(function(A) {
    var partOfItersections;
    if (A.length > 0) {
      var intersectionsCount = getIntersectionCount(A, machingArray);
      partOfItersections = intersectionsCount / A.length;
    } else {
      partOfItersections = 0
    }

    intersections.push({
      length: A.length,
      partOfItersections: partOfItersections
    });
  });


  //alert(JSON.stringify(intersections));

  var maxLength = 0,
    maxPartOfItersections = 0,
    optimalArrays = [];

  intersections.forEach(function(arrayData, index) {
    var currentArr = M[index];
    var currentArrLength = currentArr.length;
    if (maxPartOfItersections < arrayData.partOfItersections) {

      setCurrentOptimalArr(arrayData.partOfItersections, currentArr);
    } else if (maxPartOfItersections === arrayData.partOfItersections) {
      if (maxLength < currentArrLength) {
        setCurrentOptimalArr(arrayData.partOfItersections, currentArr);
      } else if (maxLength === currentArrLength) {
        optimalArrays.push(currentArr);
      }
    }
  });

  //alert(JSON.stringify(optimalArrays));

  return optimalArrays;

  function setCurrentOptimalArr(intersectionsCount, currentArr) {
    optimalArrays = [currentArr];
    maxLength = currentArr.length;
    maxPartOfItersections = intersectionsCount;
  }

  function getIntersectionCount(A, machingArray) {
    var intersectionCount = 0;

    A.forEach(function(elem) {
      if (machingArray.indexOf(elem) != -1) {
        intersectionCount++;
      }
    });


    return intersectionCount;
  }
}

alert(JSON.stringify(compareArrays(M, matchingArray)));

  1. 分别计数数组的交集。
  2. 返回数组,其中包含更多的交叉点。

代码更新的

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43428874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档