3

This is a problem based on finding size of maximal nested intervals set..

There are many intervals each defined by pair containing a starting point and a ending point (si, ei). Two intervals i1 and i2 are called nested if i2 lies completely inside of i1. Example:- (2,6) and (3,4) are nested, since (3,4) is a part of (2,6). Similarly k intervals i1, i2, i3....ik are called nested if, i2 lies inside i1, i3 lies inside i2, ...and so on. Determine size of largest set of intervals from the given intervals, such that all the intervals in that set could produce a nesting.

I thought it in following way:- Let us take an e.g.- (0,7) (0,5) (1,21) (1,9) (2,8) (2,4) (3,20) (4,16) (5,15) (6,21) Sort it in the way such that a[i-1]<=a[i] && b[i-1]>=b[i] Than starting from first interval we start a linked list.. if the next interval comes inside a interval we move down the node and traverse the graph created down the node(other than main list)..we store the pointer of the maximum level node in this graph at which the new interval can fit.. and traverse further in linked list to see under whom the current interval comes.. at last we have a pointer to a node with whom we have to attach the current interval.. and compare the level of this node with the maximum level we already have..... The final value of maximum level is size of maximal nested intervals set..

complexity of above solution is likely to be:- O(n(k+l) + nlogn)

I guess it is difficult to get it this way, but I have no other option... if anyone got any other algorithm to solve it.. please post because my algorithm will take much longer to implement(lot of data structures involved)... thanks!!!

  • 2
    Do it in N^2 if you don't want to write that much( sort them after the distance between B-A, [A,B] ) and then do 2 for loops. For a better complexity you will have to create some date structure. And what you are suggesting is an hour job + testing. – Mark Jul 03 '13 at 12:50
  • @IonescuRobert I don't understand your proposed solution. You sort the intervals by size and then what do the two loops do? – John Kurlak Apr 24 '14 at 07:16

1 Answers1

0

Edit: A few solutions to the problem are posted here, including two that claim to be O(n lg n). However, I don't think the O(n lg n) solutions work. I made comments on that page indicating why. If anyone has an O(n lg n) solution, I'd love to hear it.

Quadratic Solution

This problem can be solved in O(n^2) time using dynamic programming:

  1. Compute how many intervals each interval contains (can be done with two nested loops)
  2. Sort the intervals in ascending order of number of contained intervals
  3. Use the recurrence MaxNestedIntervals to solve the problem

*Note: Step 1 can be done in O(n lg n) time using the solution here: Sub O(n^2) algorithm for counting nested intervals? Step 2 can be done in O(n lg n) time with any optimal comparison-based sorting algorithm. There may be a way to optimize step 3, but I haven't found it yet.


Recurrence

MaxNestedIntervals(i) =
    max {j = 0 to i-1} :
        1 + MaxNestedIntervals(j)    if interval i contains interval j
        0                            if interval i doesn't contain interval j

Base case

MaxNestedIntervals(i) =
    0    if interval i contains 0 intervals
    1    if interval i contains 1 interval

Sample code

import java.util.*;

public class MaxNestedIntervals {
    public static void main(String[] args) {
        Interval[] intervals = new Interval[10];
        intervals[0] = new Interval(0, 7);
        intervals[1] = new Interval(0, 5);
        intervals[2] = new Interval(1, 21);
        intervals[3] = new Interval(1, 9);
        intervals[4] = new Interval(2, 8);
        intervals[5] = new Interval(2, 4);
        intervals[6] = new Interval(3, 20);
        intervals[7] = new Interval(4,16);
        intervals[8] = new Interval(5,15);
        intervals[9] = new Interval(6,21);

        int n = intervals.length;
        AugmentedInterval[] augmentedIntervals = new AugmentedInterval[n];

        for (int i = 0; i < n; i++) {
            augmentedIntervals[i] = new AugmentedInterval(intervals[i]);
        }

        for (int i = 0; i < n; i++) {
            AugmentedInterval outerInterval = augmentedIntervals[i];

            for (int j = 0; j < n; j++) {
                if (i == j) {
                    continue;
                }

                AugmentedInterval innerInterval = augmentedIntervals[j];

                if (outerInterval.contains(innerInterval)) {
                    outerInterval.numContainedIntervals++;

                    if (outerInterval.childInterval == null) {
                        outerInterval.childInterval = innerInterval;
                    }
                }
            }
        }

        Arrays.sort(augmentedIntervals, new Comparator<AugmentedInterval>() {
            public int compare(AugmentedInterval i, AugmentedInterval j) {
                return i.numContainedIntervals - j.numContainedIntervals;
            }
        });

        int maxNestedIntervals = 0;
        AugmentedInterval parentInterval = null;

        for (int i = 0; i < n; i++) {
            AugmentedInterval currentInterval = augmentedIntervals[i];

            if (currentInterval.numContainedIntervals == 0) {
                currentInterval.maxNestedIntervals = 0;
            } else if (currentInterval.numContainedIntervals == 1) {
                currentInterval.maxNestedIntervals = 1;
            } else {
                int maxNestedIntervalsForCurrentInterval = 0;

                for (int j = 0; j < i; j++) {
                    AugmentedInterval candidateNestedInterval = augmentedIntervals[j];
                    int maxNestedIntervalsForCurrentCandidate = candidateNestedInterval.maxNestedIntervals + 1;

                    if (currentInterval.contains(candidateNestedInterval) && maxNestedIntervalsForCurrentCandidate >= maxNestedIntervalsForCurrentInterval) {
                        maxNestedIntervalsForCurrentInterval = maxNestedIntervalsForCurrentCandidate;
                        currentInterval.childInterval = candidateNestedInterval;
                    }
                }

                currentInterval.maxNestedIntervals = maxNestedIntervalsForCurrentInterval;

                if (maxNestedIntervalsForCurrentInterval >= maxNestedIntervals) {
                    maxNestedIntervals = maxNestedIntervalsForCurrentInterval;
                    parentInterval = currentInterval;
                }
            }
        }

        if (n == 0) {
            System.out.println("The largest set of nested intervals is the empty set.");
        } else if (maxNestedIntervals == 0) {
            System.out.println("The largest set of nested intervals has 1 interval.\n");
            System.out.println("That interval is:");
        } else {
            System.out.println("The largest set of nested intervals has " + (maxNestedIntervals + 1) + " intervals.\n");
            System.out.println("Those intervals are:");
        }

        for (AugmentedInterval currentInterval = parentInterval; currentInterval != null; currentInterval = currentInterval.childInterval) {
            System.out.println(currentInterval);
        }

        System.out.println();
    }

    private static class Interval implements Comparable<Interval> {
        public int start = 0;
        public int end = 0;

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

        public int size() {
            return this.end - this.start;
        }

        public boolean contains(Interval other) {
            return (this.start <= other.start && this.end >= other.end);
        }

        public int compareTo(Interval other) {
            return this.size() - other.size();
        }

        public String toString() {
            return "[" + this.start + ", " + this.end + "]";
        }
    }

    private static class AugmentedInterval extends Interval {
        public int numContainedIntervals = 0;
        public int maxNestedIntervals = 0;
        public AugmentedInterval childInterval = null;

        public AugmentedInterval(Interval interval) {
            super(interval.start, interval.end);
        }
    }
}
Community
  • 1
  • 1
John Kurlak
  • 6,594
  • 7
  • 43
  • 59