題目:原題不公開,需求是給出大量進程的啓動和結束時間,計算任意時間點進程併發數。進程數有限,查詢次數很大。關閉開區間: [啓動,關閉)
思路:先將時間區間點排序,然後遍歷計數,遇到啓動+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;
}