题目有点绕,但实际上很简单,只要理清楚题目所描述的东西,很容易写出代码。
已知条件:
1. 音频id取模后的区间是[0,799]
2. 每个机器有一个区间[i,k],如果id%800的值落在这个区间,那么这个id的文件就落在这个机器上
3. 新增机器:实际上就是找到一个[i,k]范围最大的机器,然后一分为二,旧的机器的区间更新为[i,(i+k)/2],新机器的区间为[(i+k)/2+1,k]
思路:
1. 定义一个computer结构体用来描述机器,包含区间信息以及自己的机器id
2. 使用集合存放computer,并对其自定义排序——区间大的放在前面,如果区间一样大则索引小的放在前面
3. 集合初始化只有一个机器——范围为[0,799],机器id为1,
4. 新增机器:每次新增机器的时候都从集合的第一个元素取出范围进行划分,然后创建新的机器
5. 在每次新增机器的时候,对区间进行判断,如果id%800落在这两个机器中的一个上,则更新要返回的机器id
代码如下:
struct computer { int id_start; int id_end; int index; int range() const { return id_end - id_start; } }; struct compare_obj { // 先根据区间大小进行排序,如果区间大小一致,则根据机器编号排序 bool operator()(const computer &a, const computer &b) { if (a.range() != b.range()) { return a.range() > b.range(); } return a.index < b.index; } }; class Solution { public: int consistentHashing(int n, int ID) { std::set<computer, compare_obj> s; computer c; c.id_start = 0; c.id_end = 799; c.index = 1; s.insert(c); int index = ID % 800; int ans = 1; for (int i = 2; i <= n; ++i) { auto c = *s.begin(); s.erase(s.begin()); computer new_computer; new_computer.id_start = (c.id_start + c.id_end) / 2 + 1; new_computer.id_end = c.id_end; new_computer.index = i; c.id_end = (c.id_start + c.id_end) / 2; s.insert(c); s.insert(new_computer); if (index >= new_computer.id_start && index <= new_computer.id_end) { ans = new_computer.index; } else if (index >= c.id_start && index <= c.id_end) { ans = c.index; } } return ans; } };