Java 在集合a范围中查找连接范围

Java 在集合a范围中查找连接范围,java,algorithm,Java,Algorithm,假设我有以下一组范围: 1 -> 3 4 -> 5 7 -> 8 13 -> 15 16 -> 16 我如何获得一套: 1 -> 5 7 -> 8 13 -> 16 你为什么需要一个图书馆?这不是那么多代码 class Range{ int start , end; public Range(int start , int end){ this.start = start;

假设我有以下一组范围:

1 -> 3
4 -> 5
7 -> 8
13 -> 15
16 -> 16
我如何获得一套:

1 -> 5
7 -> 8
13 -> 16

你为什么需要一个图书馆?这不是那么多代码

class Range{         
     int start , end;

     public Range(int start , int end){
          this.start = start;
          this.end = end;
     }
}

public static void join(List<Range> ranges){
     //sort the list ascending for easier comparison
     Collections.sort(ranges , (r1 , r2) -> {
          if(r1 < r2)return -1;
          else if(r1 > r2)return 1;
          else return 0;
     });

     int tmp = 1; //counter for the position in the list
     while(tmp < ranges.size()){
          if(ranges.get(tmp).start < ranges.get(tmp - 1).end){
                //the range at position tmp intersects with the previous 
                //one -> replace with the joined ranges
                Range r = new Range(ranges.get(tmp - 1).start , ranges.get(tmp).end);
                ranges.remove(tmp);
                ranges.remove(tmp - 1);
                ranges.add(r , tmp - 1);
           }else
                tmp++;//this pair (tmp - 1 / tmp) doesn't intersect -> next pair
     }
}
我可能会使用集合。 你的代码是什么

pairs = "a -> b \n c -> d \n e -> f"
比如说

listOfPairs = pairs.split("\n")
_set = new set()
for k : listOfPairs{
    temp = k.split("->")
    _set += _set( range(temp[1],temp[2]) )
}
在这一点上,我们有一个集合,所有的数字都在这个范围内。现在我们必须检查整个范围并确定子范围

c = min(_set)
ans = ""
while(c <= max(_set)){
    if(c in _set && !(c-1 in _set) ){
        ans += string(c) + "->"
    }
    if( (c in _set) && !(c+1 in _set) ){ 
        ans += string(c) + " \n"
    }
}

这也可以通过树形图实现,树形图的键是范围开始,值是范围结束,如下所示:

public class ContinuousRangeSet {
    private TreeMap<Integer, Integer> ranges = new TreeMap<Integer, Integer>();

    public void addRange(int start, int end) {
        int effectiveStart = start, effectiveEnd = end;
        Map.Entry<Integer, Integer> previousRange = ranges.floorEntry(start);
        if (previousRange != null && previousRange.getValue() + 1 >= start) {
            // the start is in the middle of an existing range
            effectiveStart = previousRange.getKey();
        }

        SortedMap<Integer,Integer> overlappingRanges = ranges.subMap(start, true, end + 1, true);
        if (!overlappingRanges.isEmpty()) {
            Integer lastOverlappingKey = overlappingRanges.lastKey();
            if (ranges.get(lastOverlappingKey) > end) {
                // the end is in the middle of an existing range
                effectiveEnd = ranges.get(lastOverlappingKey);
            }
        }
        // we don't want to keep the overlapping ranges
        overlappingRanges.clear();

        ranges.put(effectiveStart, effectiveEnd);
    }

    public static void main(String[] args) {
        ContinuousRangeSet rangeSet = new ContinuousRangeSet();
        rangeSet.addRange(1, 3);
        rangeSet.addRange(4, 5);
        rangeSet.addRange(7, 8);
        rangeSet.addRange(13, 15);
        rangeSet.addRange(16, 16);
        System.out.println(rangeSet.ranges);

        rangeSet.addRange(3, 14);
        System.out.println(rangeSet.ranges);
    }
}

请注意,我没有测试所有的边缘情况…

您可以很容易地为此编写一个算法。请将您的问题从题外的“库查找请求”更改为其他类似的问题,例如,如何更改此。。。那。。。?。也可以考虑提供更多关于你的问题的信息,比如如果范围总是有序的,它们可以相交,等等……你可以在一个范围树中安排它。这将是一个非常容易实现的结构。请参阅以下链接。你也可以使用段树:也许这同样有帮助:按左边框排序,然后合并,如果下一个左边框,我不确定你是否可以假设范围是按顺序给出的,尽管在他的问题中它们肯定是…@kpie我没有做任何假设。我的算法做的第一件事是对范围进行排序。很抱歉,->do?@kpie是一个表示比较器的lambda表达式。
{1=5, 7=8, 13=16}
{1=16}