题目:给定一些无序区间,判断某个给定的特定区间是否在这些无序的区间内。
这个题目比较简单,首先将给定的区间排序,在对重合的区间进行排序,使得区间变成递增且不重叠的若干个区间,对于给定的区间在已经处理好的区间内进行二分查找,完成区间覆盖的判断。
程序如下:
参考文献:
编程之美2.19
这个题目比较简单,首先将给定的区间排序,在对重合的区间进行排序,使得区间变成递增且不重叠的若干个区间,对于给定的区间在已经处理好的区间内进行二分查找,完成区间覆盖的判断。
程序如下:
#include <stdio.h>
#include <vector>
#include <algorithm>
class Interval {
public:
Interval(int start, int end) : start_(start), end_(end) {}
Interval() :start_(0), end_(0) {}
static bool OrderByStart(const Interval& left, const Interval& right) {
return left.start_ < right.start_;
}
friend bool operator<(const Interval& left, const Interval& right) {
return left.start_ < right.start_;
}
int start_;
int end_;
};
void CombinInterval(std::vector<Interval>& orginal, std::vector<Interval>* combined) {
if (orginal.size() < 1) {
return;
}
sort(orginal.begin(), orginal.end(), Interval::OrderByStart);
Interval combined_interval = orginal[0];
int new_ending = orginal[0].end_;
for (int i = 1; i < orginal.size(); ++i) {
if (combined_interval.end_ >= orginal[i].start_) {
new_ending = combined_interval.end_ > orginal[i].end_ ? combined_interval.end_ : orginal[i].end_;
continue;
}
combined_interval.end_ = new_ending;
combined->push_back(combined_interval);
combined_interval = orginal[i];
new_ending = orginal[i].end_;
}
combined_interval.end_ = new_ending;
combined->push_back(combined_interval);
}
bool CoverTest(const Interval& interval, std::vector<Interval>& intervals, Interval* covered_interval) {
std::vector<Interval> combined_intervals;
CombinInterval(intervals, &combined_intervals);
for (int i = 0; i < combined_intervals.size(); ++i) {
printf("%d-%d\n", combined_intervals[i].start_, combined_intervals[i].end_);
}
if (combined_intervals.size() < 1) {
return false;
}
int start = 0;
int end = combined_intervals.size() -1;
int middle = 0;
bool found = false;
while (end >= start) {
middle = (start + end) / 2;
if (interval < combined_intervals[middle]) {
end = middle - 1;
} else if (combined_intervals[middle] < interval) {
start = middle + 1;
} else {
found = true;
break;
}
}
int target_index = found ? middle : start - 1;
printf("target:%d\n", target_index);
if (target_index >= 0 &&
combined_intervals[target_index].start_ <= interval.start_ &&
combined_intervals[target_index].end_ >= interval.end_) {
*covered_interval = combined_intervals[target_index];
return true;
} else {
return false;
}
}
int main(int argc, char** argv) {
std::vector<Interval> intervals;
intervals.push_back(Interval(2,5));
intervals.push_back(Interval(3,4));
intervals.push_back(Interval(4,7));
intervals.push_back(Interval(9,13));
Interval target_interval(3, 4);
Interval covered_interval;
if (CoverTest(target_interval, intervals, &covered_interval)) {
printf("the covered interval is (%d, %d)\n", covered_interval.start_, covered_interval.end_);
} else {
printf("uncovered\n");
}
}
程序编写时开始犯了几个错误:
1、函数参数开始使用了const 修饰,导致sort时出错
2、区间合并时,没有将最后一个加入到向量中,new_ending设置的初值也要注意,开始就出错了
3、二分查找,找下界时,需要将查找过程走几遍就比较清楚了,下界是start-1,但如果start为0,下界可能是负数,要注意处理。另外循环条件是start <=end,等号也很重要,如果判断过程中只有一个元素时,就是等号覆盖的情况。
参考文献:
编程之美2.19