【发布时间】:2016-03-03 11:12:46
【问题描述】:
在尝试提高我的算法技能时,我发现自己陷入了以下问题,简而言之,该问题要求您找出房间内人数最多的时间跨度的持续时间:
https://jutge.org/problems/P27158_en
我提出的解决方案对于网站建议的所有公共测试用例都正确解决了问题,但对于一个或多个隐藏的私有测试用例却失败了。
我的解决方案在 std::vector 中为每个事件保存两个条目:一个用于到达,一个用于离开,每个都由 [eventtype, eventtime] 组成。然后按事件时间对向量进行排序,最后循环遍历向量以确定客人最多的时间跨度的持续时间。我的代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
enum class EventType {ARRIVE, LEAVE};
struct Event{
int time;
EventType type;
Event(){}
Event(int tm, EventType t) : time(tm), type (t){}
// inline bool operator<(const Event& e) const {return time < e.time || (time == e.time && type==EventType::LEAVE);}
};
bool eventCompare(const Event& e1, const Event& e2) {
if(e1.time < e2.time){
return true;
} else if(e1.time == e2.time) {
if(e1.type == EventType::LEAVE && e2.type == EventType::ARRIVE) {
return true;
} else {
return false;
}
} else {
return false;
}
}
int main()
{
int visits;
int timeStart, timeEnd;
int maxVisits, maxDuration, localMaxVisits, localStartTime, localEndTime, duration;
std::vector<Event> events;
std::vector<Event>::const_iterator it;
// Get each Case from stdin.
// 0 is the special stopping case.
while(cin>>visits && visits!=0) {
events.clear();
// Read all the visits, for each one save two entries to the visits-vector,
// one for the arrival time another for the leaving time.
for(int i=1; i<=visits; ++i){
cin>>timeStart>>timeEnd;
Event eStart(timeStart, EventType::ARRIVE);
Event eEnd(timeEnd, EventType::LEAVE);
events.push_back(eStart);
events.push_back(eEnd);
}
// Sorting the vector so that events are ordered by their arrival time.
// In case two events coincide on arrival time, we place leaving events before arrival events.
std::sort(events.begin(), events.end(), eventCompare);
maxVisits=0;
maxDuration=0;
localMaxVisits=0;
localStartTime=0;
localEndTime=0;
// Loop through the sorted vector
for(it=events.begin(); it!=events.end(); ++it){
// If the event type is arrival
if((*it).type == EventType::ARRIVE) {
// We only reset the localStartTime if there is no
// gap between the last endtime and the current start time
// For example two events 11-13 and 13-15 should be treated as one long event
// with duration 11-15
if(localEndTime < (*it).time) {
localStartTime = (*it).time;
}
localMaxVisits++;
} else { // Event type leave
// Calculate the duration
duration = (*it).time - localStartTime;
// If we have a new max in overlaps or equal overlaps but larger duration than previous
// We save as the global max.
if(localMaxVisits > maxVisits || (localMaxVisits == maxVisits && duration>maxDuration)) {
maxVisits=localMaxVisits;
maxDuration = duration;
}
localMaxVisits--;
localEndTime= (*it).time;
}
}
cout<<maxVisits<<" "<<maxDuration<<endl;
}
return 0;
}
我已经根据@j_random_hacker 的评论修改了代码,程序现在没有像以前对隐藏的私人测试用例那样超过时间限制,但现在得到一个“错误答案”的判决(仅适用于私人测试例)。我将尝试找出算法错误可能是什么。感谢所有回答的人。
【问题讨论】:
-
算法对我来说看起来不错。你有没有描述什么花了这么长时间?是 std::sort() 还是其他什么?或者您是否在没有编译器优化的情况下编译它,并且它们将运行时间限制与优化的程序对齐?
-
我没有尝试分析执行,但搜索文档我得出结论,std::sort 应该是对向量进行排序的最快方法。换句话说,即使我发现 std::sort 在大型数据集中需要相对较长的时间,我也不知道应该使用哪种排序算法。但你是对的,我应该检查代码的哪一部分是主要的时间消费者。至于你的另一个问题,我只将源代码提交到测试站点,所以我不知道他们用哪些编译器设置编译并稍后执行我的程序。
-
我认为
sort不应该是您应该首先考虑加快算法速度的地方。相反,我相信循环的内容对算法的速度更为重要。然而,正如 Heinzi 所指出的,剖析肯定会帮助您确定算法的瓶颈。 -
如果我错了,请原谅我,但算法似乎是 O(n)。
-
std::sort()需要一个描述 total 订单的比较函数,但是您给出的那个可以说a < b和b < a如果它们的时间是真的相等,最左边的是 LEAVE。这在理论上(甚至在实践中)可能会导致std::sort()崩溃或挂起。
标签: c++ algorithm sorting overlap