我有一个数组数组和一个匹配数组。每个数组都有唯一的 id 值。
匹配数组 = [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 有最大可能的交集。
对于此示例,有 2 种可能的匹配具有最大交集:M1 = [[2,3,5], [1, 4, 6]] 和 M2 = [[1,5], [4], [ 1, 6]]。但是 M1.length < M2.length,所以算法应该输出 M1。
最佳答案
您可以使用集合(或散列,无论语言如何调用它们)来优化时间效率。
将目标数组转换为集合,然后从中减去选定的源(即删除公共(public)值)。递归地继续这样做,直到目标集为空。跟踪最佳结果(尽可能使用最少的源阵列)。如果正在使用的源数组的数量超过当时已找到的最佳解决方案的长度,则回溯。
这是 Python 中的代码:
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 中:
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);
.as-console-wrapper { max-height: 100% !important; top: 0; }
关于algorithm - 找到最佳阵列交点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43428874/