思路
要求三个方法都是O(1)的时间复杂度
使用一个HashMap存储server_id(key)和对应的index(value),可以使得put和remove的时间都为常数级
使用一个ArrayList存储所有的server_id,方便通过索引随机pick一台服务器
remove方法:在arraylist中删除元素,如果仅仅使用其自带的remove方法,时间复杂度为O(n), 因为相当于在数组中删除元素,需要进行待删除元素后面所有元素的前移。因此在这里可以将待删除的元素先与数组中最后一个元素交换,然后删除最后一个元素即可。
remove的实现:在交换待删除元素与最后一个元素的地方,由于要删除的server_id已经知道,所以只需要将最后一个位置的值覆盖待删除元素即可。然后在hashmap中更新其索引。后面remove的地方也要在hashmap中删除相应的k-v pair。
复杂度
时间复杂度:三个方法都是constant time
空间复杂度:整体是O(n), n为服务器的数量,每个方法都是O(1)
代码
public class LoadBalancer {
Random rand;
// key: server_id
// value: index
Map<Integer, Integer> hash;
List<Integer> serverList;
public LoadBalancer() {
// do intialization if necessary
rand = new Random();
hash = new HashMap<>();
serverList = new ArrayList<>();
}
/*
* @param server_id: add a new server to the cluster
* @return: nothing
*/
public void add(int server_id) {
// write your code here
hash.put(server_id,serverList.size());
serverList.add(server_id);
}
/*
* @param server_id: server_id remove a bad server from the cluster
* @return: nothing
*/
public void remove(int server_id) {
// write your code here
// swap the element to be deleted with the last element, then remove the last element.
int index = hash.get(server_id);
int length = serverList.size();
int lastElement = serverList.get(length-1);
// also update the HashMap
serverList.set(index,lastElement);
hash.put(lastElement,index);
// also update the HashMap
serverList.remove(length-1);
hash.remove(server_id);
}
/*
* @return: pick a server in the cluster randomly with equal probability
*/
public int pick() {
// write your code here
return serverList.get(rand.nextInt(serverList.size()));
}
}
注意在remove方法中,要同时