哈希表:插入、删除、随机访问时间复杂度都为O(1)

题目

https://leetcode-cn.com/problems/FortPu/

解题思路

看到时间复杂度O(1)就可以联想到数组或者哈希表。 这里情况特殊需要考虑getRandom函数,且返回一个相同概率的随机数。所以要实现这个目标,只能从数组里面返回,且数组具有索引。

那么这个题目我们可以设计成的数据结构是: 哈希表: 要修改的元素作为key,而元素的索引作为value。 数组:用来保存元素,且数组索引可以用来生成一个随机数,可以返回一个以随机数作为数组下标的数。

如何从数组中用时间复杂度O(1)来删除一个元素?

这里最容易出错的地方是删除一个数。 数组中删除一个数,需要把数组遍历一次,才能找到被删除的数,这样时间复杂度是O(n); 所以我们得用一个其他技巧: 每次首先把列表最后一个数和要删除的数(其下标我们已经用哈希表作为value存好)交换。交换后,每次固定删除列表最后一个数即可,这样时间复杂度达到O(1);

具体代码如下:

代码

class RandomizedSet {
          
   

    //哈希表能实现删除,查询O(1)时间复杂度。
    Map<Integer, Integer> numToLocation = null;

    //想要生成一个相同概率的随机数,则需要列表索引,而哈希表不具有索引,我们得借助数组来完成。
    //Nums里面保存值。 而HashMap的值保存索引。
    ArrayList<Integer> nums = null;
    /** Initialize your data structure here. */
    public RandomizedSet() {
          
   
        numToLocation = new HashMap<>();
        nums = new ArrayList<>();
    }
    
    /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
    public boolean insert(int val) {
          
   
        if(numToLocation.containsKey(val)){
          
   
            return false;
        }

        numToLocation.put(val, nums.size());
        nums.add(val);
        return true;
    }
    
    /** Removes a value from the set. Returns true if the set contained the specified element. */
    public boolean remove(int val) {
          
   
        if(!numToLocation.containsKey(val)) {
          
   
            return false;
        }
        int location = numToLocation.get(val);
        numToLocation.put(nums.get(nums.size() - 1), location);
        numToLocation.remove(val);
        nums.set(location, nums.get(nums.size() - 1));
        nums.remove(nums.size() - 1);
        return true;
    }
    
    /** Get a random element from the set. */
    public int getRandom() {
          
   
       Random random = new Random();
       int key = random.nextInt(nums.size());
       return nums.get(key);
    }
}

/**
 * Your RandomizedSet object will be instantiated and called as such:
 * RandomizedSet obj = new RandomizedSet();
 * boolean param_1 = obj.insert(val);
 * boolean param_2 = obj.remove(val);
 * int param_3 = obj.getRandom();
 */

总结

本题考察哈希表和数组的性质,时间复杂度O(1)。同时如何结合哈希表来删除数组一个数,且时间复杂度O(1)。

经验分享 程序员 微信小程序 职场和发展