2019.11.10 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)
github:https://github.com/ChopinXBP/LeetCode-Babel
数据结构题,应知应会。
HashSet可以用二维数组进行动态开辟空间,避免直接开辟过大的一维数组造成资源浪费。
HashMap容量初始为16,需要考虑负载,一旦数量-容量比大于负载系数(0.75),进行再散列,将容量扩大为原来的两倍(保持2的幂次)。
在2的幂次的容量的情况下,哈希值计算有:
key & (length - 1) == key % length
补充:
java中HashSet底层其实是HashMap,HashSet的add方法底层调用HashMap的put方法,添加的value是一个固定的Object对象常量PRESENT。
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
Design a HashSet without using any built-in hash table libraries.
To be specific, your design should include these functions:
add(value): Insert a value into the HashSet.
contains(value) : Return whether the value exists in the HashSet or not.
remove(value): Remove a value in the HashSet. If the value does not exist in the HashSet, do nothing.
不使用任何内建的哈希表库设计一个哈希集合
具体地说,你的设计应该包含以下的功能
add(value):向哈希集合中插入一个值。
contains(value) :返回哈希集合中是否存在这个值。
remove(value):将给定值从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
示例:
MyHashSet hashSet = new MyHashSet();
hashSet.add(1);
hashSet.add(2);
hashSet.contains(1); // 返回 true
hashSet.contains(3); // 返回 false (未找到)
hashSet.add(2);
hashSet.contains(2); // 返回 true
hashSet.remove(2);
hashSet.contains(2); // 返回 false (已经被删除)
注意:
所有的值都在 [1, 1000000]的范围内。
操作的总数目在[1, 10000]范围内。
不要使用内建的哈希集合库。
/**
*
* Design a HashSet without using any built-in hash table libraries.
* 不使用任何内建的哈希表库设计一个哈希集合
*
*/
public class DesignHashSet {
class MyHashSet {
private int buckets = 1000;
private int itemsPerBucket = 1001;
private boolean[][] table;
/** Initialize your data structure here. */
public MyHashSet() {
table = new boolean[buckets][];
}
//计算哈希值(商对应桶组)
public int hash(int key){
return key / buckets;
}
//计算位置(余数对应桶号)
public int pos(int key){
return key % buckets;
}
public void add(int key) {
int hashkey = hash(key);
if(table[hashkey] == null){
table[hashkey] = new boolean[itemsPerBucket];
}
table[hashkey][pos(key)] = true;
}
public void remove(int key) {
int hashkey = hash(key);
if(table[hashkey] != null){
table[hashkey][pos(key)] = false;
}
}
/** Returns true if this set contains the specified element */
public boolean contains(int key) {
int hashkey = hash(key);
return table[hashkey] != null && table[hashkey][pos(key)];
}
}
/**
* 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);
*/
}
Design a HashMap without using any built-in hash table libraries.
To be specific, your design should include these functions:
put(key, value) : Insert a (key, value) pair into the HashMap. If the value already exists in the HashMap, update the value.
get(key): Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key.
remove(key) : Remove the mapping for the value key if this map contains the mapping for the key.
不使用任何内建的哈希表库设计一个哈希映射
具体地说,你的设计应该包含以下的功能
put(key, value):向哈希映射中插入(键,值)的数值对。如果键对应的值已经存在,更新这个值。
get(key):返回给定的键所对应的值,如果映射中不包含这个键,返回-1。
remove(key):如果映射中存在这个键,删除这个数值对。
示例:
MyHashMap hashMap = new MyHashMap();
hashMap.put(1, 1);
hashMap.put(2, 2);
hashMap.get(1); // 返回 1
hashMap.get(3); // 返回 -1 (未找到)
hashMap.put(2, 1); // 更新已有的值
hashMap.get(2); // 返回 1
hashMap.remove(2); // 删除键为2的数据
hashMap.get(2); // 返回 -1 (未找到)
注意:
所有的值都在 [1, 1000000]的范围内。
操作的总数目在[1, 10000]范围内。
不要使用内建的哈希库。
/**
*
* Design a HashMap without using any built-in hash table libraries.
* 不使用任何内建的哈希表库设计一个哈希映射
*
*/
public class DesignHashMap {
class MyHashMap {
private class Node{
int key;
int value;
Node next;
public Node(int k, int v, Node n){
key = k;
value = v;
next = n;
}
}
private final double LOAD_FACTOR = 0.75;
private Node[] nodes;
private int size;
/** Initialize your data structure here. */
public MyHashMap() {
nodes = new Node[16];
size = 0;
}
//计算哈希值(当length为2的幂次时,key & (length - 1) == key % length)
private int hash(int key){
return key & (nodes.length - 1);
}
//每次再散列成原数组的两倍
private void rehash(){
Node[] temp = nodes;
nodes = new Node[temp.length << 1];
size = 0;
for(Node head : temp){
for(Node p = head; p != null; p = p.next){
put(p.key, p.value);
}
}
}
/** value will always be non-negative. */
public void put(int key, int value) {
int hashkey = hash(key);
//先遍历链表里是否已经存在相同key值,若存在则覆盖value
for(Node p = nodes[hashkey]; p != null; p = p.next){
if(p.key == key){
p.value = value;
return;
}
}
//若链表中不存在则将结点加在开头
nodes[hashkey] = new Node(key, value, nodes[hashkey]);
size++;
//若当前size比例超过负债系数,则进行再散列
if((double)size / nodes.length > LOAD_FACTOR){
rehash();
}
}
/** 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 hashkey = hash(key);
for(Node p = nodes[hashkey]; p != null; p = p.next){
if(p.key == key){
return p.value;
}
}
return -1;
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
public void remove(int key) {
int hashkey = hash(key);
Node newhead = new Node(-1, -1, nodes[hashkey]);
for(Node p = newhead; p.next != null; p = p.next){
if(p.next.key == key){
p.next = p.next.next;
size--;
break;
}
}
nodes[hashkey] = newhead.next;
}
}
/**
* 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);
*/
}
#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#