Implement a load balancer for web servers. It provide the following functionality:
- Add a new server to the cluster =>
add(server_id)
. - Remove a bad server from the cluster =>
remove(server_id)
. - Pick a server in the cluster randomly with equal probability =>
pick()
.
At beginning, the cluster is empty. When pick()
is called you need to randomly return a server_id
in the cluster.
Example
Example 1:
Input:
add(1)
add(2)
add(3)
pick()
pick()
pick()
pick()
remove(1)
pick()
pick()
pick()
Output:
1
2
1
3
2
3
3
Explanation: The return value of pick() is random, it can be either 2 3 3 1 3 2 2 or other.
思路:跟 Insert Delete GetRandom O(1) 类似,server_id都是unique的,所以用list和hashmap就可以解决,delete的操作就是把最后一个元素给index的元素,注意要特殊判断一下index就是最后一个元素的情况;一定要考虑remove就是最后一个元素的情况,然后考虑remove是中间的情况;
public class LoadBalancer {
private List<Integer> list;
private HashMap<Integer, Integer> serverToIndex;
public LoadBalancer() {
// serverId, Index;
serverToIndex = new HashMap<Integer, Integer>();
list = new ArrayList<Integer>();
}
/*
* @param server_id: add a new server to the cluster
* @return: nothing
*/
public void add(int server_id) {
list.add(server_id);
int index = list.size() - 1;
serverToIndex.put(server_id, index);
}
/*
* @param server_id: server_id remove a bad server from the cluster
* @return: nothing
*/
public void remove(int server_id) {
int lastIndex = list.size() - 1;
int lastServerId = list.get(lastIndex);
int badIndex = serverToIndex.get(server_id);
// 一定要考虑remove的就是最后一个的情况;
if(badIndex == lastIndex) {
list.remove(lastIndex);
serverToIndex.remove(server_id);
} else {
// 然后考虑remove是中间的情况;
list.set(badIndex, lastServerId);
serverToIndex.put(lastServerId, badIndex);
list.remove(lastIndex);
serverToIndex.remove(server_id);
}
}
/*
* @return: pick a server in the cluster randomly with equal probability
*/
public int pick() {
int n = list.size();
Random random = new Random();
int randomIndex = random.nextInt(n);
return list.get(randomIndex);
}
}