How to get overlap range of two range

后端 未结 4 1525
眼角桃花
眼角桃花 2020-12-21 09:25

I have the following ranges in interval [1-15]

I want to find the overlap ranges between people 1 & 2.

Person1 [1, 3] [5, 10] Person2 [2, 4] [8, 15]

相关标签:
4条回答
  • 2020-12-21 09:49

    Sort the starts and ends of the ranges.. keeping information alongside as to whether its a range-start or finish... for your example you'll get this:

    1 start
    2 start
    3 end
    4 end
    5 start
    8 start
    10 end
    15 end
    

    Now loop over these points and keep a counter.. +1 for a start -1 for an end. This counter is the number of overlapping segments at any time. If you want the boundaries you need to test each time you increase or decrease the counter. If you increase it from 1 to 2 this is a start of an overlapping range.. the end of the overlapping range will be when you decrease the counter from 2 to 1

    Martin

    0 讨论(0)
  • 2020-12-21 09:55

    Thanks for the clarification. What about something like this...

    public static IList<Range> GetListIntersections(IList<Range> rangeList1, IList<Range> rangeList2)
    {
        var intersection = new List<Range>();
    
        //add intersection of each range
        foreach (var x in rangeList1)
        {
            foreach (var y in rangeList2)
            {
                var intersect = GetIntersection(x, y);
                if (intersect != null)
                {
                    intersection.Add(intersect);
                }
            }
        }
    
        //remove ranges that are subsets of other ranges
        intersection.RemoveAll(x => intersection.Any(y => y != x && y.Start >= x.Start && y.End <= x.End));
    
        return intersection;
    }
    
    public static Range GetIntersection(Range range1, Range range2)
    {
        int greatestStart = range1.Start > range2.Start ? range1.Start : range2.Start;
        int smallestEnd = range1.End < range2.End ? range1.End : range2.End;
    
        //no intersection
        if (greatestStart > smallestEnd)
        {
            return null;
        }
    
        return new Range { Start = greatestStart, End = smallestEnd };
    }
    
    0 讨论(0)
  • 2020-12-21 10:03

    I don't understand how you're looping by 'person1's range, then by person2's ranges' - I'm not sure what that means without seeing the code.

    I can't see how you would get better than O(n), but you can iterate through the range only once. A better data structure might be a bool[] or BitArray.

    var person1 = new bool[15] { /* set values */ };
    var person2 = new bool[15] { /* set values */ };
    
    var overlap = new bool[15];
    
    for (int i = 0; i < 15; i++)
    {
        overlap[i] = person1[i] && person2[i];
    }
    
    0 讨论(0)
  • 2020-12-21 10:05

    Have a look at the merge step of the mergesort algorithm. If the ranges for each person are sorted this method can be adapted to compute the overlaps very easily.

    Loop
       Get the range that starts next (R1)
       if the next range of the other person (R2) starts before R1 ends
          Add the range from begin of R2 and min( end of R1 end of R2 ) to results
       Increase the counter for the person which gave you R1
    

    If your ranges are known to be non adjacent (i.e. if there is always at least one number between to consecutive ranges). The solution will also be. Else you might need an extra compaction step to ensure that adjacent ranges will be put into one range.

    The nice thing is that this works for any ordered type and not just ints, and you can intersect any number of ranges very fast ( O(n+m) ).

    0 讨论(0)
提交回复
热议问题