Alternative to 14.8?

#1

The “the interval covering problem” may have a nice mathematical intuition behind an alternative solution, with trivial data structures. Keep in mind that I am slightly noobish so I may be wrong (again), but hey nothing beats learning from mistakes :wink:

Anyway: After sorting on left endpoints, starting from the left we can keep intersecting the intervals, the resulting intervals are non increasing and will eventually yield an empty intersection (If all tasks overlap at one common point then it wont be empty, but it is a corner case and it doesn’t change intuition). The last non empty interval is the smallest interval with elements that are common to all intersected intervals so far.
So the recipe goes like this:

  • sort the intervals on left endpoint
  • while there remain intervals{
  • select current interval
    
  • while there remain intervals{
    
  •     keep intersecting current with next interval, until intersection is empty, then take any endpoints (left or right) of the last non empty interval as a visit time}}
    
struct Interval
{
	unsigned int left, right;
	Interval(int l, int r) :left(l), right(r){}
	bool operator<(const Interval &that){return this->left < that.left;}
};
bool Intersect(Interval &a, const Interval &b) {
	if (min(a.right, b.right) < max(a.left, b.left))
		return false; //empty intersection
	a.left = max(a.left, b.left);
	a.right= min(a.right, b.right);
	return true;
}
vector Prob14_8(vector v) {
	vector result;
	sort(v.begin(), v.end());
	int i = 0;
	while (i != v.size()) {
		Interval in = v[i];
		while (i != v.size() && Intersect(in, v[i]))
			++i;
		result.push_back(in.left);
	}
	return result;
}

Let me know if you find some errors ! I have a simple test code if you want to try

void Prob14_8D() {
	vector tasks;
	tasks.push_back(Interval(0, 3)); tasks.push_back(Interval(2, 4)); 
	tasks.push_back(Interval(3, 4)); tasks.push_back(Interval(1, 1));
	tasks.push_back(Interval(5, 7)); tasks.push_back(Interval(7, 8)); 
	tasks.push_back(Interval(8, 11)); tasks.push_back(Interval(9, 11));
	tasks.push_back(Interval(12, 14)); tasks.push_back(Interval(12, 16)); 
	tasks.push_back(Interval(13, 13)); tasks.push_back(Interval(16, 17));
	vector results(Prob14_8(tasks));
	for (const int &v : results)
		cout << v << " ";
}
0 Likes

Simpler solution to Points Covering Intervals
#2

This seems a very interesting algorithm to me. Because you are trying to greedily intersect as many as intervals until you cannot make it. This definitely matches the key idea of solving this problem–greedy algorithm. Of course, there is another benefit brought by this algorithm is that it does not need advance data structure.

I will try to compare this algorithm with the one in the book for further correctness verification. Will let you know if I found any error.

Again, thanks for your awesome idea!

0 Likes

#3

I just tried to implement this program and it runs perfect fine to all the static and automatic tests I have. Thanks again for proving such simple and elegant algorithm!

1 Like