例如:一组线段[1,5]、[2,8]、[2,9]、[6,10]、[7,11]、[8,16]交集部分,达到3次的,结果应该是[2,5]、[8,10]
先将线段平铺到横坐标上,
记录每个点所在集合的数量,得到一个map,key存储每个点,value存储该点被包含的集合数量
然后过滤掉不满足指定次数的数据
/**
* 计算交集部分达到指定次数
*
* @param sourceList 线段集合
* @param number 次数
* @return
*/
private List<ArticleHighlightDto> overlapList(List<ArticleHighlightDto> sourceList, int number) {
if (CollectionUtils.isEmpty(sourceList)) {
return new ArrayList<>();
}
//选取最大的终点
int end = sourceList
.stream()
.map(ArticleHighlightDto::getEndPos)
.max((k1, k2) -> k1 - k2)
.get();
//计算每个点被覆盖的次数
Map<Integer, Integer> pointMap = new HashMap<>();
for (int temp = sourceList.get(0).getStartPos(); temp <= end; temp++) {
for (ArticleHighlightDto articleHighlight : sourceList) {
int pointNumber = pointMap.getOrDefault(temp, 0);
//达到指定热度后就不再计算
if (pointNumber >= number) {
continue;
}
if (temp >= articleHighlight.getStartPos() && temp <= articleHighlight.getEndPos()) {
pointMap.put(temp, pointNumber + 1);
}
}
}
//过滤掉不满足条件的点
List<Integer> pointList = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : pointMap.entrySet()) {
if (entry.getValue() >= number) {
pointList.add(entry.getKey());
}
}
if (CollectionUtils.isEmpty(pointList)) {
return new ArrayList<>();
}
//将满足条件的点排序
pointList = pointList.stream().sorted().collect(Collectors.toList());
//将连续的点连接起来
List<ArticleHighlightDto> result = new ArrayList<>();
ArticleHighlightDto articleHighlightDto = new ArticleHighlightDto();
articleHighlightDto.setStartPos(pointList.get(0));
for (int i = 1; i < pointList.size(); i++) {
if (pointList.get(i) - pointList.get(i - 1) == 1) {
continue;
} else {
articleHighlightDto.setEndPos(pointList.get(i - 1));
if(articleHighlightDto.getStartPos() != articleHighlightDto.getEndPos()){
result.add(articleHighlightDto);
}
articleHighlightDto = new ArticleHighlightDto();
articleHighlightDto.setStartPos(pointList.get(i));
}
}
articleHighlightDto.setEndPos(pointList.get(pointList.size() - 1));
if(articleHighlightDto.getStartPos() != articleHighlightDto.getEndPos()){
result.add(articleHighlightDto);
}
return result;
}
|