对于原题,书上写的很详细,即图的着色问题,这里主要看第一个扩展和leetcode上相关的问题
扩展问题一:
简单的说就是:有 N 个面试要同时进行, 他们的面试时间分别是 B[i], E[i]. 我们希望将这N个面试安排在若干地点, 不同的面试在同一时间不能再相同的面试点. 问至少需要多少个面试点
思路:先按照开始时间排序,对每个节点赋颜色值时,在它之前开始并且有时间重叠的区域的颜色不能使用
struct Interval {
int start;
int end;
int color;
Interval() : start(0), end(0),color(-1) {}
Interval(int s, int e,int c) : start(s), end(e) ,color(c) {}
};
bool operator<(const Interval& lhs,const Interval& rhs)
{
return (lhs.start < rhs.start || (lhs.start == rhs.start && lhs.end < rhs.end));
}
bool isOverLap(const Interval& lhs,const Interval& rhs)
{
if(lhs.start >= rhs.start && lhs.start < rhs.end)return true;
if(rhs.start >= lhs.start && rhs.start < lhs.end)return true;
return false;
}
int interviewPoint(vector<Interval>& intervals)
{
sort(intervals.begin(),intervals.end());//按开始时间排序
int length = intervals.size();
vector<bool>isForbidden(length+1,false);
int i,j,maxColor = 1;
for(i = 0; i < length;++i)
{
for(j = 0;j < i;++j)
{
if(isOverLap(intervals[i],intervals[j]))isForbidden[intervals[j].color] = true;//如果区域重叠,则它的颜色不能使用
}
for(j = 1;j <= maxColor;++j)
{
if(isForbidden[j] == false)break;
}
if(j > maxColor)intervals[i].color = ++maxColor;
else intervals[i].color = j;
isForbidden.assign(length+1,false);
}
return maxColor;
}
编程之美上说,如果只需要求出面试点的个数,则可以对所有开始结束时间进行排序,然后遍历,这里有一点没有说清楚,就是当结束时间和开始时间相同时,要把所有的结束时间放在前面,具体如下:
struct Interval {
int start;
int end;
Interval() : start(0), end(0) {}
Interval(int s, int e,int c) : start(s), end(e){}
};
struct Time //用于排序
{
int time;
bool isStart;//标记
Time(int t,bool s):time(t),isStart(s){}
};
bool operator<(const Time& lhs,const Time& rhs)
{
return (lhs.time < rhs.time || lhs.time == rhs.time && !lhs.isStart); //时间相同时,结束时间在前
}
int interviewPoint(vector<Interval>& intervals)
{
vector<Time> data;
int i,maxColor = 0,count = 0;
for(i = 0;i < intervals.size();++i)
{
data.push_back(Time(intervals[i].start,true));
data.push_back(Time(intervals[i].end,false));
}
sort(data.begin(),data.end());
for(i = 0; i < data.size();++i) //遇到开始时间,加1,遇到结束时间,减1
{
if(data[i].isStart)
{
if(++count > maxColor)maxColor = count;
}
else --count;
}
return maxColor;
}
leetcode上两个和时间段相关的问题
Merge Intervals
Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18]
,
return [1,6],[8,10],[15,18]
.
思路:这个题目比较简单,就是先按照开始时间排序,然后遍历整个数组,用两个指针指向相邻的两个位置,如果需要合并,就合并,不需要合并就得到一个结果。
struct Interval {
int start;
int end;
Interval() : start(0), end(0) {}
Interval(int s, int e) : start(s), end(e) {}
};
bool operator<(const Interval& lhs,const Interval& rhs)
{
return (lhs.start < rhs.start || (lhs.start == rhs.start && lhs.end < rhs.end));
}
class Solution {
public:
vector<Interval> merge(vector<Interval>& intervals) {
sort(intervals.begin(),intervals.end());//按照开始时间排序
vector<Interval> res;
vector<Interval>::iterator iter = intervals.begin();
Interval* cur = NULL;
for(;iter != intervals.end();++iter)//进行时间段的合并
{
if(cur != NULL)
{
if(cur -> end >= iter -> start)
{
cur -> end = (cur -> end > iter -> end) ? cur -> end : iter -> end;//这里改变了原来的数据,面试的时候要具体对待
}
else
{
res.push_back(*cur);
cur = &(*iter);
}
}
else cur = &(*iter);
}
if(cur)res.push_back(*cur);
return res;
}
};
Insert Interval
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1:
Given intervals [1,3],[6,9]
, insert and merge [2,5]
in as [1,5],[6,9]
.
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16]
, insert and merge [4,9]
in as [1,2],[3,10],[12,16]
.
This is because the new interval [4,9]
overlaps with [3,5],[6,7],[8,10]
.
思路:把原链表分成三段,首尾是不需要进行合并的,中间是需要进行合并的,为了加快速度,可以用二分查找定位到第一个需要合并的节点的位置。
class Solution {
public:
int binarySearch(vector<Interval> &intervals,Interval newInterval)//定位到第一个需要合并的节点的位置
{
int left = 0,right = intervals.size() - 1;
while(left <= right)
{
int mid = left + ((right - left) >> 1);
if(intervals[mid].end < newInterval.start)left = mid + 1;
else right = mid - 1;
}
return left;
}
vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
if(intervals.size() == 0)return vector<Interval>(1,newInterval);
vector<Interval> res;
int pos = binarySearch(intervals,newInterval);
int i;
for(i = 0; i < pos;++i)res.push_back(intervals[i]);//地一段
for(;i < intervals.size();++i)//第二段
{
if(intervals[i].start >= newInterval.start && intervals[i].start <= newInterval.end || newInterval.start >= intervals[i].start && newInterval.start <= intervals[i].end)
{
newInterval.start = min(newInterval.start,intervals[i].start);
newInterval.end = max(newInterval.end,intervals[i].end);
}
else break;
}
res.push_back(newInterval);
for(;i < intervals.size();++i) res.push_back(intervals[i]);//第三段
return res;
}
};