你可以使用集(或哈希值,无论语言称他们),以优化的时间效率。
将目标数组转换为一个集合,然后从中减去所选的源(即删除公共值)。继续递归直到目标集合为空。跟踪最佳结果(尽可能使用最少的源数组)。如果正在使用的源数组的数量超过了当时已经找到的最佳解决方案的长度,则返回。
这里是在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; }
如果需要更多的描述,请留下评论根据回答 –
也许问题描述不好,但算法的全部含义是找到M1。我定义了M1和M2来解释最优解,并不是因为它们在算法中是已知的。 – VahagnNikoghosian
你需要找到更多的'A1-A5'与'MatchingArray'相交的数组? –