前言
设计题,为满足查询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] LeetCode 原题