Find index of closest non-overlapping interval to right of each of given N intervals


A standard representation for intervals usually entails a set of starting and ending points arranged in pairs. Finding the nearest non-overlapping interval to the right of each designated interval constitutes our current dilemma. This task bears immense significance across many different applications such as resource allocation and scheduling since it involves identifying the following interval that does not intersect with or include the present one.

Syntax

To aid in comprehension of the forthcoming code demonstrations, let us first examine the syntax that will be utilized before delving into the algorithm −

// Define the Interval structure
struct Interval {
   int start;
   int end;
};

// Function to find the index of closest non-overlapping interval
vector findClosestNonOverlappingInterval(const vector& intervals) {
   // Implementation goes here
}

Algorithm

Resolving this issue requires an organized approach centered around iterating through the intervals in reverse order whilst maintaining a stack of indices that point towards their nearest non-overlapping partners in succession. Here are brief but effective steps outlining how our proposed algorithm tackles this problem −

  • Create an empty stack to store the indices of the non-overlapping intervals.

  • Initialize a vector of indices with a size equal to the number of intervals, filled with -1 to indicate no non-overlapping interval found yet.

  • Iterate through the intervals from right to left.

  • In case of a non-empty stack and if there exists a cross-sectional area between both current and top intervals, then proceed to eliminate (pop) that topmost index from said stack.

  • To ensure accurate representation, assign a value of -1 to the index position in the vector representing current intervals should there be an empty stack. This indicates that there exist no non-overlapping intervals towards the right.

  • It is highly recommended one makes sure our designated stack has elements before attempting this task; otherwise expect an error. After confirming we have an element or more on said structure, we can progress by having our current interval's vector set its index value identical to its counterpart at top-most position on our identified structure as well as including its corresponding index information onto this same structure.

  • Repeat steps 3-7 until all intervals have been processed.

  • Return the vector of indices.

Approaches

To resolve this predicament, we shall examine two disparate strategies.

Approach 1: Brute Force

A possible strategy for addressing this issue entails employing brute force. Essentially this necessitates examining every individual interval and subsequently comparing it with all intervals located to its right until an option free from intersections becomes apparent. However. It is significant to acknowledge that utilizing this method produces a time complexity of O(N^2). Where N denotes the total quantity of intervals engaged in the examination procedure.

Syntax

vector<int> findClosestNonOverlappingInterval(const vector<Interval>& intervals) {
   vector<int> result(intervals.size(), -1);
   for (int i = 0; i < intervals.size(); i++) {
      for (int j = i + 1; j < intervals.size(); j++) {
         if (intervals[i].end < intervals[j].start) {
            result[i] = j;
            break;
         }
      }
   }
   return result;
}

Example

#include <iostream>
#include <vector>

using namespace std;

// Define the Interval structure
struct Interval {
   int start;
   int end;
};

vector<int> findClosestNonOverlappingInterval(const vector<Interval>& intervals) {
   vector<int> result(intervals.size(), -1);
   for (int i = 0; i < intervals.size(); i++) {
      for (int j = i + 1; j < intervals.size(); j++) {
         if (intervals[i].end < intervals[j].start) {
            result[i] = j;
            break;
         }
      }
   }
   return result;
}

int main() {
   // Define intervals
   vector<Interval> intervals = {{1, 3}, {2, 4}, {5, 7}, {6, 9}, {8, 10}};

   // Find the index of closest non-overlapping interval for each interval
   vector<int> closestIndices = findClosestNonOverlappingInterval(intervals);

   // Print the results
   for (int i = 0; i < intervals.size(); i++) {
      cout << "Interval [" << intervals[i].start << ", " << intervals[i].end << "] ";
      if (closestIndices[i] != -1) {
         cout << "has closest non-overlapping interval at index " << closestIndices[i] << endl;
      } else {
         cout << "has no non-overlapping interval to the right" << endl;
      }
   }
   return 0;
}

Output

Interval [1, 3] has closest non-overlapping interval at index 2
Interval [2, 4] has closest non-overlapping interval at index 2
Interval [5, 7] has closest non-overlapping interval at index 4
Interval [6, 9] has no non-overlapping interval to the right
Interval [8, 10] has no non-overlapping interval to the right

Approach 2: Optimal Solution

A highly successful approach involves utilizing a stack as a means of monitoring the closest non-overlapping intervals. This strategy boasts a time complexity of O(N) since our task solely requires that we peruse through the intervals just one time.

Syntax

vector<int> findClosestNonOverlappingInterval(const vector<Interval>& intervals) {
   vector<int> result(intervals.size(), -1);
   stack<int> st;
   for (int i = intervals.size() - 1; i >= 0; i--) {
      while (!st.empty() && intervals[i].end >= intervals[st.top()].start) {
         st.pop();
      }
      if (!st.empty()) {
         result[i] = st.top();
      }
      st.push(i);
   }
   return result;
}

Example

#include <iostream>
#include <vector>

using namespace std;

// Define the Interval structure
struct Interval {
   int start;
   int end;
};

vector<int> findClosestNonOverlappingInterval(const vector<Interval>& intervals) {
   vector<int> result(intervals.size(), -1);
   for (int i = 0; i < intervals.size(); i++) {
      for (int j = i + 1; j < intervals.size(); j++) {
         if (intervals[i].end < intervals[j].start) {
            result[i] = j;
            break;
         }
      }
   }
   return result;
}

int main() {
   // Define intervals
   vector<Interval> intervals = {{1, 3}, {2, 4}, {5, 7}, {6, 9}, {8, 10}};
   
   // Find the index of closest non-overlapping interval for each interval
   vector<int> closestIndices = findClosestNonOverlappingInterval(intervals);
   
   // Print the results
   for (int i = 0; i < intervals.size(); i++) {
      cout << "Interval [" << intervals[i].start << ", " << intervals[i].end << "] ";
      if (closestIndices[i] != -1) {
         cout << "has closest non-overlapping interval at index " << closestIndices[i] << endl;
      } else {
         cout << "has no non-overlapping interval to the right" << endl;
      }
   }
   return 0;
}

Output

Interval [1, 3] has closest non-overlapping interval at index 2
Interval [2, 4] has closest non-overlapping interval at index 2
Interval [5, 7] has closest non-overlapping interval at index 4
Interval [6, 9] has no non-overlapping interval to the right
Interval [8, 10] has no non-overlapping interval to the right

Conclusion

Our exploration aims to uncover how best to locate each given interval's closest non-overlapping interval index situated on its right in C++. To begin with, we delved into discussing syntax intricacies while presenting an algorithm and proposing two potential solutions. As part of our investigation, we showcased how both our brute force approach and our stack-based optimized method function through successfully tested executable codes. This methodology enables you to identify any specific set's closest non-overlapping intervals with ease.

Updated on: 25-Jul-2023

49 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements