Recently I see a frequently-seen design question: design a data structure and support the following operations for the Server class:
- Add a Server.
- Delete a Server.
- Select a Server randomly.
The time complexity of all the preceding operations must be O (1 ). To abstract this question, we need to design a data structure that supports the insert, remove, and find random of O (1.
In O (1) time, there are not many data structures that support the first two operations, so it is easy to think of hash tables. The key is how to support the random selection operation of HashMap. Here, we assume that both the key and value are integer types. The java code is as follows:
Random random = new Random();List<Integer> keys = new ArrayList<Integer>(map.keySet());Integer randomKey = keys.get(random.nextInt(keys.size()));int randomElem = map.get(randomKey);
The idea is simple, because it is very easy to obtain a random element for an array. With this property, you can first obtain the key set in HashMap, map it to an array, and then randomly generate an array subscript to randomly specify a key. With such a random key, you can get a random element.
Unfortunately, the above method is not strictly O (1) time, because generating an ArrayList actually requires copying all the keys in the HashMap. Unless the HashMap is read-only, the elements are no longer added or deleted, and then the array is saved for future use, so that the O (1) Time is evenly distributed.
However, the answer here is actually very close. Since HashMap can meet the first two conditions, and array can meet the first 3rd conditions, we can mix and match them, design a data structure that contains an array and a HashMap.
1. Insert: add the server to the HashMap and array (tail) respectively. In addition, overwrite the corresponding array elements by the elements at the end of the array, and remove the end elements.
2. Delete: first obtain the corresponding array subscript of the server to be deleted, and then Delete the server from HashMap. In addition, the corresponding array element is overwritten by the element at the end of the array, and the array subscript of the element at the end of the original array in HashMap is deleted.
3. Find Random: Randomly select an array subscript in the array and use the corresponding server as the key to search for it in HashMap.
The Code is as follows:
public class Servers {private List<Server> servers = new ArrayList<Server>();// key: server; value: array indexprivate Map<Server, Integer> serverMap = new HashMap<Server, Integer>();public void add(Server server) {servers.add(server);serverMap.put(server, servers.size() - 1);}public void remove(Server server) {int index = serverMap.get(server);serverMap.remove(server);servers.set(index, servers.get(servers.size() - 1));serverMap.put(servers.get(index), index);servers.remove(servers.size() - 1);}public Server findRandom() {if (servers.size() == 0)return null;Random random = new Random();int randomKey = random.nextInt(servers.size());return servers.get(randomKey);}}