Hash Set
class MyHashSet {
private final int MAX_LEN = 100000; // the amount of buckets
private List<Integer>[] set; // hash set implemented by array
/** Returns the corresponding bucket index. */
private int getIndex(int key) {
return key % MAX_LEN;
}
/** Search the key in a specific bucket. Returns -1 if the key does not existed. */
private int getPos(int key, int index) {
// Each bucket contains a list.
List<Integer> temp = set[index];
if (temp == null) {
return -1;
}
// Iterate all the elements in the bucket to find the target key.
for (int i = 0; i < temp.size(); ++i) {
if (temp.get(i) == key) {
return i;
}
}
return -1;
}
/** Initialize your data structure here. */
public MyHashSet() {
set = new ArrayList[MAX_LEN];
}
public void add(int key) {
int index = getIndex(key);
int pos = getPos(key, index);
if (pos < 0) {
// Add new key if key does not exist.
if (set[index] == null) {
set[index] = new ArrayList<Integer>();
}
set[index].add(key);
}
}
public void remove(int key) {
int index = getIndex(key);
int pos = getPos(key, index);
if (pos >= 0) {
// Remove the key if key exists.
set[index].remove(pos);
}
}
/** Returns true if this set did not already contain the specified element */
public boolean contains(int key) {
int index = getIndex(key);
int pos = getPos(key, index);
return pos >= 0;
}
}
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet obj = new MyHashSet();
* obj.add(key);
* obj.remove(key);
* boolean param_3 = obj.contains(key);
*/
Hash Map
import javafx.util.Pair;
class MyHashMap {
private final int MAX_LEN = 100000; // the amount of buckets
private List<Pair<Integer, Integer>>[] map; // hash map implemented by array
/** Returns the corresponding bucket index. */
private int getIndex(int key) {
return key % MAX_LEN;
}
/** Search the key in a specific bucket. Returns -1 if the key does not existed. */
private int getPos(int key, int index) {
// Each bucket contains a list.
List<Pair<Integer, Integer>> temp = map[index];
if (temp == null) {
return -1;
}
// Iterate all the elements in the bucket to find the target key.
for (int i = 0; i < temp.size(); ++i) {
if (temp.get(i).getKey() == key) {
return i;
}
}
return -1;
}
/** Initialize your data structure here. */
public MyHashMap() {
map = new ArrayList[MAX_LEN];
}
/** value will always be positive. */
public void put(int key, int value) {
int index = getIndex(key);
int pos = getPos(key, index);
if (pos < 0) {
// Add new (key, value) pair if key is not existed.
if (map[index] == null) {
map[index] = new ArrayList<Pair<Integer, Integer>>();
}
map[index].add(new Pair(key, value));
} else {
// Update the value if key is existed.
map[index].set(pos, new Pair(key, value));
}
}
/** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
public int get(int key) {
int index = getIndex(key);
int pos = getPos(key, index);
if (pos < 0) {
return -1;
} else {
return map[index].get(pos).getValue();
}
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
public void remove(int key) {
int index = getIndex(key);
int pos = getPos(key, index);
if (pos >= 0) {
map[index].remove(pos);
}
}
}
/**
* Your MyHashMap object will be instantiated and called as such:
* MyHashMap obj = new MyHashMap();
* obj.put(key,value);
* int param_2 = obj.get(key);
* obj.remove(key);
*/
优化删除操作的两个小技巧
因为每一个bucket是用数组来存储元素,当删除一个元素后,后面的元素要整体往前移动,所以remove()的时间复杂度为O(n)。有如下两个办法可以将其优化到O(1):
- 交换。将要删除的元素的值和数组最后一个元素交换,然后删除最后一个元素。
- 链表。用链表替换数组存储元素。
查找的时间复杂度
查找操作的时间复杂度和Hash Table的设计有关。如果每一个bucket是用数组存储元素,那么查找的时间复杂度是O(n),n为这个数组中的元素个数。JDK8中是用链表来存储,但当bucket中的元素个数超过某一个阈值时,则改用红黑树进行存储,这样就把查找的时间复杂度降到O(logn)。
插入操作同理。