题目有点绕,但实际上很简单,只要理清楚题目所描述的东西,很容易写出代码。
已知条件:
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;
}
};

京公网安备 11010502036488号