设计一个查询、删除、随机访问都是O(1)的容器
前言
设计题,为满足查询O(1)可以使用Map,为了使随机访问O(1)可以使用数组存储元素。两种数据结构联动,但是删除O(1)变有了问题,如果删除一个中间元素,则Map里面存的下标全部错乱,此时可以使用最后节点覆盖被删节点来完成下标不错乱。 注:需要注意删除的就是最后一个元素,此时不需要更新map,更新会导致下标越界。
一、案例
二、题解
package com.xhu.offer.offerII; import java.util.*; //插入、删除、随机访问都是O(1)的容器 public class RandomizedSet { //Map来O(1)访问+确定下标在那里,数组 + random来O(1)访问。 //关键问题,如何不让下标整体位移。可以用最后一个值去覆盖,只需要修改最后一个值的下标就可以了。 Map<Integer, Integer> cache; List<Integer> el; Random rand; /** * Initialize your data structure here. */ public RandomizedSet() { cache = new HashMap<>(); el = new ArrayList<>(); rand = new Random(); } /** * Inserts a value to the set. Returns true if the set did not already contain the specified element. */ public boolean insert(int val) { if (cache.containsKey(val)) return false; cache.put(val, el.size()); el.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 (!cache.containsKey(val)) return false; int idx = cache.get(val); cache.remove(val); if (el.size() == 1 || el.size() == idx + 1) { el.remove(el.size() - 1); return true; } el.remove(idx - 0); el.add(idx, el.get(el.size() - 1)); el.remove(el.size() - 1); cache.put(el.get(idx), idx); return true; } /** * Get a random element from the set. */ public int getRandom() { return el.get(rand.nextInt(el.size())); } }
总结
1)数据结构间相互组合,能够实现丰富的功能。 2)数组删除元素,可以使用最后值覆盖中间删除值来达到O(1)时间复杂度+小标不错位。
参考文献
[1]
下一篇:
查找算法:哈希算法,哈希表查找