Java daily question -- > sword finger Offer II 030 Insert, delete, and random access are all O's containers

Posted by Stressed on Sat, 25 Dec 2021 17:54:50 +0100

This is [030 on LeetCode. Insert, delete and random access are O(1) containers], and the difficulty is [medium]

subject

Design a data structure that supports the following operations under the average time complexity O(1):

  • insert(val): returns true when the element val does not exist, and inserts the item into the collection; otherwise, returns false.
  • remove(val): returns true when the element val exists, and removes the item from the collection; otherwise, returns false.
  • getRandom: returns an item in an existing collection at random. Each element should have the same probability of being returned.

Problem solution

Train of thought analysis

According to the first two conditions of the meaning of the question, the time complexity of insertion and deletion is O(1). It is easy to think of using a hash table. The insertion, deletion and search of an element only need O(1). The last condition of the meaning of the question returns a data randomly, and the probability of each data returned is required to be equal. Obviously, the hash table does not meet this condition, The following is illustrated by implementing HashMap of hash table in java as an example

The bottom layer adopts array + linked list + red black tree. In addition to storing elements, each element of the array also has a reference variable to point to the next element (linked list). It finds the element by finding the remainder of the hash value of the element (hash function) to determine the position of the element in the array. There may be a linked list in the position of the array to store other elements (the hash value is the same), so it cannot return each value with equal probability.

Return each element with equal probability. Obviously, the array meets this condition. Assuming that the length of the array is n, the probability of each element being returned is 1/n

To sum up, we should design a container containing hash tables and arrays

Because each element needs to be returned with equal probability, the data can only be stored in the array. You can use the java dynamic array ArrayList, and it meets the first and third conditions, but it does not meet the second condition. For example, to delete an element, you need to do the following two operations

  • Traverse the array to find the element to be deleted. When deleting the last element, you need to traverse the array. The time complexity is O(n). When deleting the first element, it is O(1)
  • When the element to be deleted is found, if the last element is deleted, the time complexity is O(1). When the first element is deleted, all elements of the first element need to be moved forward, and the time complexity is O(n)

To sum up, the time complexity of deleting elements of the array is O(n), so we need to use HashMap to solve the above two problems

Solve the first problem

The key of HashMap is used to store the element, and the value is used to store the index of the element in the array. Therefore, when deleting the element, it is not necessary to traverse the array to find the deleted element. The index of the deleted element can be obtained through the map key, and the time complexity is O(1)

Solve the second problem

When we find the location of the deleted element in the array, we only need to replace its value body with the value of the last element of the array, and then delete the last element. The time complexity of deleting the last element of the array is O(1), and there is no need to move the element. Since the value of the last element of the array is assigned to the location where the element is deleted, the index of the last element of the HashMap needs to be changed

code implementation

public class RandomizedSet {

    private HashMap<Integer, Integer> numToLocation;
    private ArrayList<Integer> nums;
    Random random = new Random();

    public RandomizedSet() {
        numToLocation = new HashMap<>();
        nums = new ArrayList<>();
    }

    public boolean insert(Integer val) {
        // Determine whether the inserted element exists and the array through the map
        if (numToLocation.containsKey(val)){
            return false;
        }
        // There is no execution logic
        // Record the position of the inserted element in the array. Each insertion is at the end of the array, so the index is the length of the array
        numToLocation.put(val, nums.size());
        // Adds an element to the end of the array
        nums.add(val);
        return true;
    }

    public boolean remove(Integer val) {
        // Judge whether the deleted element exists in the array through the map
        if (!numToLocation.containsKey(val)) {
            return false;
        }
        // There is execution logic
        // Get the index of deleted elements in the array through map
        Integer location = numToLocation.get(val);
        // Gets the last element of the array
        Integer lastNum = nums.get(nums.size() - 1);
        // Replace the value of the element to be deleted in the array with the last element of the array
        nums.set(location, lastNum);
        // Deletes the last element of the array
        nums.remove(nums.size() - 1);
        // Change the index of the last element of the array into the index of the deleted element through map
        numToLocation.put(lastNum, location);
        // Delete the index of the element to be deleted from the map
        numToLocation.remove(val);
        return true;
    }

    public Integer getRandom() {
        // Assuming that the array length is n, a random number between [0 ~ n-1] is generated
        int i = random.nextInt(nums.size());
        return nums.get(i);
    }
}

Topics: Java Algorithm data structure