用于元素成对比较的高效算法
给定一个包含一些键值对的数组:
[
{'a': 1, 'b': 1},
{'a': 2, 'b': 1},
{'a': 2, 'b': 2},
{'a': 1, 'b': 1, 'c': 1},
{'a': 1, 'b': 1, 'c': 2},
{'a': 2, 'b': 1, 'c': 1},
{'a': 2, 'b': 1, 'c': 2}
]
我想找到这些对的交集。交叉意味着只留下那些可以被其他人覆盖的元素,或者是唯一的。例如,和 完全覆盖 ,而 是唯一的。所以,在{'a': 1, 'b': 1, 'c': 1}
{'a': 1, 'b': 1, 'c': 2}
{'a': 1, 'b': 1}
{'a': 2, 'b': 2}
[
{'a': 1, 'b': 1},
{'a': 2, 'b': 1},
{'a': 2, 'b': 2},
{'a': 1, 'b': 1, 'c': 1},
{'a': 1, 'b': 1, 'c': 2},
{'a': 2, 'b': 1, 'c': 1},
{'a': 2, 'b': 1, 'c': 2}
]
找到交叉路口后应保留
[
{'a': 2, 'b': 2},
{'a': 1, 'b': 1, 'c': 1},
{'a': 1, 'b': 1, 'c': 2},
{'a': 2, 'b': 1, 'c': 1},
{'a': 2, 'b': 1, 'c': 2}
]
我试图迭代所有对,并找到相互比较的覆盖对,但时间复杂度等于。是否有可能在线性时间中找到所有覆盖或唯一对?O(n^2)
这是我的代码示例 ():O(n^2)
public Set<Map<String, Integer>> find(Set<Map<String, Integer>> allPairs) {
var results = new HashSet<Map<String, Integer>>();
for (Map<String, Integer> stringToValue: allPairs) {
results.add(stringToValue);
var mapsToAdd = new HashSet<Map<String, Integer>>();
var mapsToDelete = new HashSet<Map<String, Integer>>();
for (Map<String, Integer> result : results) {
var comparison = new MapComparison(stringToValue, result);
if (comparison.isIntersected()) {
mapsToAdd.add(comparison.max());
mapsToDelete.add(comparison.min());
}
}
results.removeAll(mapsToDelete);
results.addAll(mapsToAdd);
}
return results;
}
其中 MapComparison 是:
public class MapComparison {
private final Map<String, Integer> left;
private final Map<String, Integer> right;
private final ComparisonDecision decision;
public MapComparison(Map<String, Integer> left, Map<String, Integer> right) {
this.left = left;
this.right = right;
this.decision = makeDecision();
}
private ComparisonDecision makeDecision() {
var inLeftOnly = new HashSet<>(left.entrySet());
var inRightOnly = new HashSet<>(right.entrySet());
inLeftOnly.removeAll(right.entrySet());
inRightOnly.removeAll(left.entrySet());
if (inLeftOnly.isEmpty() && inRightOnly.isEmpty()) {
return EQUALS;
} else if (inLeftOnly.isEmpty()) {
return RIGHT_GREATER;
} else if (inRightOnly.isEmpty()) {
return LEFT_GREATER;
} else {
return NOT_COMPARABLE;
}
}
public boolean isIntersected() {
return Set.of(LEFT_GREATER, RIGHT_GREATER).contains(decision);
}
public boolean isEquals() {
return Objects.equals(EQUALS, decision);
}
public Map<String, Integer> max() {
if (!isIntersected()) {
throw new IllegalStateException();
}
return LEFT_GREATER.equals(decision) ? left : right;
}
public Map<String, Integer> min() {
if (!isIntersected()) {
throw new IllegalStateException();
}
return LEFT_GREATER.equals(decision) ? right : left;
}
public enum ComparisonDecision {
EQUALS,
LEFT_GREATER,
RIGHT_GREATER,
NOT_COMPARABLE,
;
}
}