题目:原题不公开,需求是给出大量进程的启动和结束时间,计算任意时间点进程并发数。进程数有限,查询次数很大。关闭开区间: [启动,关闭)
思路:先将时间区间点排序,然后遍历计数,遇到启动+1,遇到关闭-1,时间点切换时,就得出上个值到当前值区间的进程数
接口定义如下:
void number_of_tasks_running(
OUT int result[], //输出结果
IN int start[], //启动时间点
IN int end[], //结束时间点
IN int n, //进程数
IN int query[], //查询种子
IN int m) //查询数量
原版本代码所有算法都是自行实现的,效率要好一些但是篇幅偏长,下文的代码用stl简化了一下
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define IN
#define OUT
#define INT_MIN 0
#define INT_MAX 0x7fffffff
typedef enum
{
S_START,
S_END,
} status_t;
class Node
{
public:
status_t m_type;
int m_value;
Node(){}
Node(int value, status_t type):m_type(type), m_value(value){}
bool operator<(const Node& n2) const
{
return m_value < n2.m_value || (m_value == n2.m_value && m_type == S_START); //升序排列,开始在前
}
};
class Range
{
public:
uint32_t m_beg;
uint32_t m_end;
Range(uint32_t beg, uint32_t end) : m_beg(beg), m_end(end) {}
bool operator<(const Range& n2) const
{
if(n2.m_beg >= m_beg && n2.m_end < m_end)
return false;
return m_beg < n2.m_beg;
}
};
/*
* 功能:合并区间,计数
*/
void CountRange(vector<Node>& points, map<Range, int>& rst)
{
if(points.size() < 2)
return;
//计算合并区间数
int cnt = 0;
int last = INT_MIN;
int beg = last;
for(vector<Node>::iterator itr = points.begin(); itr != points.end(); itr++)
{
if(itr->m_value != last)
{
rst[Range(beg, itr->m_value)] = cnt;
last = itr->m_value;
beg = last;
}
if(itr->m_type == S_START)
cnt++;
else
cnt--;
}
rst[Range(beg, INT_MAX)] = 0; //后开区间
}
/*
* 功能:计算并行任务数量
*/
void number_of_tasks_running(
OUT int result[],
IN int start[],
IN int end[],
IN int n,
IN int query[],
IN int m)
{
//点序列
vector<Node> points;
points.resize(2*n);
for(int i = 0; i < n; i++)
{
points[i] = Node(start[i], S_START);
points[i+n] = Node(end[i], S_END);
}
//排序,计算最小一致区间
sort(points.begin(), points.end());
map<Range, int> rst;
CountRange(points, rst);
//
for(map<Range, int>::iterator itr = rst.begin(); itr != rst.end(); itr++)
printf("%d - %d %d\n", itr->first.m_beg, itr->first.m_end, itr->second);
//
for(int i = 0; i < m; i++)
{
map<Range, int>::iterator itr = rst.find(Range(query[i], query[i]+1));
result[i] = itr->second;
}
}
//以下是测试代码
/*
* 功能:打印数组
*/
void dump_array(int arr[], int size, const char* info)
{
int i;
printf("%s\t:[", info);
for(i = 0; i < size; i++)
printf("%2d, ", arr[i]);
printf("]\n");
}
int main(int agc, char* argv[])
{
int start[] = {0, 2, 5};
int end[] = {4, 7, 8};
int n = sizeof(start)/sizeof(int);
int query[] = {1, 9, 4, 3, -1, 0, 2, 4, 5, 7, 8};
int m = sizeof(query)/sizeof(int);
int* rst = new int[m];
number_of_tasks_running(rst, start, end , n, query, m);
dump_array(start, n, "start");
dump_array(end, n, "end");
dump_array(query, m, "query");
dump_array(rst, m, "out");
delete rst;
return 0;
}