Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 基于投影点对时间间隔进行分组的最佳方法_Algorithm_Sorting - Fatal编程技术网

Algorithm 基于投影点对时间间隔进行分组的最佳方法

Algorithm 基于投影点对时间间隔进行分组的最佳方法,algorithm,sorting,Algorithm,Sorting,假设我们已经对时间间隔列表进行了排序(按开始时间排序)。 我正在寻找将这些间隔“投影”到axis的最佳解决方案,其结果是一个对象数组,描述:投影间隔开始和结束时间以及属于投影间隔的源间隔数组 让我解释一下示例:假设我们有4个间隔作为输入(按开始时间排序,然后按结束时间排序): 在这种情况下,我希望得到5个元素的数组,每个元素是一个描述间隔开始/结束的对象和一个源间隔列表。图表中轴下的数字显示该列表中的项目数 请帮我找到解决这项任务的最快方法像这样的事情 def groupIntervals(in

假设我们已经对时间间隔列表进行了排序(按开始时间排序)。 我正在寻找将这些间隔“投影”到axis的最佳解决方案,其结果是一个对象数组,描述:投影间隔开始和结束时间以及属于投影间隔的源间隔数组

让我解释一下示例:假设我们有4个间隔作为输入(按开始时间排序,然后按结束时间排序):

在这种情况下,我希望得到5个元素的数组,每个元素是一个描述间隔开始/结束的对象和一个源间隔列表。图表中轴下的数字显示该列表中的项目数

请帮我找到解决这项任务的最快方法

像这样的事情

def groupIntervals(intervals):
    events = {}
    for start, stop, name in intervals:
        if start not in events: events[start] = []
        events[start].append(('start', name))
        if stop not in events: events[stop] = []
        events[stop].append(('stop', name))
    last = None
    output = []
    active = set()
    for time in sorted(events.keys()):
        if active and last is not None:
            output.append((last, time, active.copy()))
        last = time
        for action, name in events[time]:
            if action == 'start': active.add(name)
            elif action == 'stop': active.remove(name)
            else: assert False
    return output
用法示例:

>>> groupIntervals([(1, 3, 'R1'), (2, 5, 'R2'), (2, 6, 'R3'),
...                 (4, 6, 'R4')])
[(1, 2, set(['R1'])),
 (2, 3, set(['R1', 'R2', 'R3'])),
 (3, 4, set(['R2', 'R3'])),
 (4, 5, set(['R4', 'R2', 'R3'])),
 (5, 6, set(['R4', 'R3']))]
C++版本,数据结构使用更灵活

#include <cstdio>
#include <limits>
#include <list>
#include <queue>
#include <string>
#include <vector>

struct Interval {
  Interval(std::string name, int start, int stop);
  std::string name;
  int start;
  int stop;
};

Interval::Interval(std::string name, int start, int stop)
    : name(name), start(start), stop(stop) {
}

typedef std::list<std::vector<Interval>::const_iterator> ActiveList;

struct StopEvent {
  StopEvent(int stop, ActiveList::iterator j);
  int stop;
  ActiveList::iterator j;
};

StopEvent::StopEvent(int stop, ActiveList::iterator j)
    : stop(stop), j(j) {
}

struct StopEventGreater {
  bool operator()(StopEvent const& a,
                  StopEvent const& b) const;
};

bool StopEventGreater::operator()(StopEvent const& a,
                                  StopEvent const& b) const {
  return a.stop > b.stop;
}

void Sweep(std::vector<Interval> const& intervals) {
  std::vector<Interval>::const_iterator i(intervals.begin());
  std::priority_queue<StopEvent,
      std::vector<StopEvent>,
      StopEventGreater> active_queue;
  ActiveList active_list;
  int last_time(std::numeric_limits<int>::min());
  while (i != intervals.end() || !active_queue.empty()) {
    bool start(i != intervals.end() &&
               (active_queue.empty() || i->start < active_queue.top().stop));
    int time(start ? i->start : active_queue.top().stop);
    if (time != last_time && !active_list.empty()) {
      std::printf("[%d, %d):", last_time, time);
      for (ActiveList::const_iterator j(active_list.begin());
           j != active_list.end();
           ++j) {
        std::printf(" %s", (*j)->name.c_str());
      }
      std::putchar('\n');
    }
    last_time = time;
    if (start) {
      active_queue.push(StopEvent(i->stop,
                                  active_list.insert(active_list.end(), i)));
      ++i;
    } else {
      active_list.erase(active_queue.top().j);
      active_queue.pop();
    }
  }
}

int main(void) {
  std::vector<Interval> intervals;
  intervals.push_back(Interval("R1", 0, 4));
  intervals.push_back(Interval("R2", 1, 9));
  intervals.push_back(Interval("R3", 1, 11));
  intervals.push_back(Interval("R4", 6, 11));
  Sweep(intervals);
}
#包括
#包括
#包括
#包括
#包括
#包括
结构间隔{
间隔(std::字符串名称,int开始,int停止);
std::字符串名;
int启动;
int stop;
};
间隔::间隔(std::字符串名称,int开始,int停止)
:名称(name)、开始(start)、停止(stop){
}
typedef std::list ActiveList;
结构停止事件{
StopEvent(int-stop,ActiveList::iterator j);
int stop;
ActiveList::迭代器j;
};
StopEvent::StopEvent(int-stop,ActiveList::迭代器j)
:停止(停止),j(j){
}
结构停止事件更大{
布尔运算符()(StopEvent常量&a,
停止事件常数&b)常数;
};
bool StopEventGreater::operator()(StopEvent常量&a,
StopEvent常量和b)常量{
返回a.stop>b.stop;
}
无效扫描(标准::向量常量和间隔){
std::vector::const_迭代器i(interval.begin());
std::优先级队列活动队列;
活动列表活动列表;
int last_time(std::numeric_limits::min());
while(i!=interval.end()| |!active_queue.empty()){
bool start(i!=interval.end()&&
(active_queue.empty()|i->startstart:active_queue.top().stop);
if(time!=最后一次&&!活动列表.empty()){
标准::printf(“[%d,%d):”,最后一次,时间);
对于(ActiveList::const_迭代器j(active_list.begin());
j!=active_list.end();
++(j){
std::printf(“%s”,(*j)->name.c_str());
}
std::putchar('\n');
}
最后一次=时间;
如果(启动){
活动队列推送(StopEvent(i->stop),
active_list.insert(active_list.end(),i));
++一,;
}否则{
active_list.erase(active_queue.top().j);
活动的_queue.pop();
}
}
}
内部主(空){
std::向量间隔;
间隔。推回(间隔(“R1”,0,4));
间隔。推回(间隔(“R2”,1,9));
间隔。推回(间隔(“R3”,1,11));
间隔。推回(间隔(“R4”,6,11));
扫描(间隔);
}

最后我找到了最有效的方法。它使用一个排序操作和O(N*2)次迭代来生成结果

公共IEnumerable项目(IList项)
{
if(items.Count i.DateRange.DateTimeTo).ToList();
var active=新列表();
DateTime?last=null;
foreach(TwoArrayIterator中的var对(项目,背书))
{
DateTime current=pair.Key==1?pair.Value.DateRange.DateTimeFrom:pair.Value.DateRange.DateTimeTo;
if(last!=null&¤t!=last)
{
返回新的DateProjectedItems
{
DateRange=新的日期范围(last.Value,current),
Items=active.ToList()
};
}
if(pair.Key==1)
{
active.Add(pair.Value);
}
其他的
{
活动。删除(对值);
}
last=当前值;
}             
}
}
公共IEnumerable两数组迭代器(IList arr1,IList arr2)
{
var index1=0;
var index2=0;
而(index1=arr1.Count)
返回新的KeyValuePair(2,arr2[index2++]);
否则如果(index2>=arr2.Count)
返回新的KeyValuePair(1,arr1[index1++]);
其他的
{
var elt1=arr1[index1];
var elt2=arr2[index2];
if(elt1.DateRange.DateTimeFrom
谢谢您的回答。我非常喜欢Python的清晰性。它是一种很棒的语言。但它的简单性有时是危险的。您正在广泛使用哈希(字典)。测试复杂性不是一件容易的事情。在哈希之后,您使用“排序”,这又使计算和复杂性复杂化了。A我相信应该有更有效的方法来解决这个问题。@ZlobnyiSerg
事件
散列只是在块中处理已排序的列表。
活动的
散列被链表操作取代。对停止时间进行排序基本上是必要的。渐进复杂性E是O(排序(n)),这是最佳的。@ ZLoNyNISErg今天我一定心情非常好。参见C++版本。
#include <cstdio>
#include <limits>
#include <list>
#include <queue>
#include <string>
#include <vector>

struct Interval {
  Interval(std::string name, int start, int stop);
  std::string name;
  int start;
  int stop;
};

Interval::Interval(std::string name, int start, int stop)
    : name(name), start(start), stop(stop) {
}

typedef std::list<std::vector<Interval>::const_iterator> ActiveList;

struct StopEvent {
  StopEvent(int stop, ActiveList::iterator j);
  int stop;
  ActiveList::iterator j;
};

StopEvent::StopEvent(int stop, ActiveList::iterator j)
    : stop(stop), j(j) {
}

struct StopEventGreater {
  bool operator()(StopEvent const& a,
                  StopEvent const& b) const;
};

bool StopEventGreater::operator()(StopEvent const& a,
                                  StopEvent const& b) const {
  return a.stop > b.stop;
}

void Sweep(std::vector<Interval> const& intervals) {
  std::vector<Interval>::const_iterator i(intervals.begin());
  std::priority_queue<StopEvent,
      std::vector<StopEvent>,
      StopEventGreater> active_queue;
  ActiveList active_list;
  int last_time(std::numeric_limits<int>::min());
  while (i != intervals.end() || !active_queue.empty()) {
    bool start(i != intervals.end() &&
               (active_queue.empty() || i->start < active_queue.top().stop));
    int time(start ? i->start : active_queue.top().stop);
    if (time != last_time && !active_list.empty()) {
      std::printf("[%d, %d):", last_time, time);
      for (ActiveList::const_iterator j(active_list.begin());
           j != active_list.end();
           ++j) {
        std::printf(" %s", (*j)->name.c_str());
      }
      std::putchar('\n');
    }
    last_time = time;
    if (start) {
      active_queue.push(StopEvent(i->stop,
                                  active_list.insert(active_list.end(), i)));
      ++i;
    } else {
      active_list.erase(active_queue.top().j);
      active_queue.pop();
    }
  }
}

int main(void) {
  std::vector<Interval> intervals;
  intervals.push_back(Interval("R1", 0, 4));
  intervals.push_back(Interval("R2", 1, 9));
  intervals.push_back(Interval("R3", 1, 11));
  intervals.push_back(Interval("R4", 6, 11));
  Sweep(intervals);
}