leetcode-1.两数之和
throw & throws
throw
在demoproc()方法的try语句块中,应用throw语句抛出一个NullPointerException异常,该异常被demoproc()方法的catch语句捕获,执行catch语句的代码,首先输出"Caught inside demoproc."语句到控制台,随后再次应用throw语句抛出NullPointerException异常,抛出的异常被main方法的catch语句捕获,输出异常信息。输出结果如下图所示:
throws
我们对如果方法声明后有throw语句,则在此方法被调用时,需要在调用方法中用try和catch进行异常捕获,如果不捕获异常,则需要在调用方法中使用throws语句将异常抛出。
当覆盖抛出异常的方法时,覆盖方法仅需要声明异常的同类或子类。例如,如果父类方法抛出IOException,则覆盖方法可以抛出IOException、FileNotFoundException(IOException的子类),但不可以抛出Exception(IOException的父类)。
异常
IllegalArgumentException
非法参数异常。报这个异常说明传入的参数违反了一个方法要求的某些特性。
哈希函数
构造方法
- 直接定制法
H(key)=a*key+b / H(key)=key MOD p - 数字分析法
针对有规律的数字 - 平方取中法
如果关键字的每一位都有某些数字重复出现频率很高的现象,可以先求关键字的平方值,通过平方扩大差异,而后取中间数位作为最终存储地址。
哈希冲突
- 开放定制法
$ H_i=(H_k+d_i) mod m $,其中 d i d_i di 有3种取法:
1)线性探测再散列—— d i = c ∗ i d_i=c∗i di=c∗i
2)平方探测再散列—— d i = 1 2 , − 1 2 , 2 2 , − 2 2 di=1^2,−1^2,2^2,−2^2 di=12,−12,22,−22 ……
3)随机探测在散列(双探测再散列)
是一组伪随机数列 - 链地址法
产生hash冲突后在存储数据后面加一个指针,指向后面冲突的数据 - 公共溢出区法
建立一个特殊存储空间,专门存放冲突的数据。此种方法适用于数据和冲突较少的情况。 - 再散列法
准备若干个hash函数,如果使用第一个hash函数发生了冲突,就使用第二个hash函数,第二个也冲突,使用第三个……
查找
如果数组arr[index]的值为空 则查找不成功
如果数组arr[index]== key 则查找成功
效率
决定hash表查找的ASL因素:
- 选用的hash函数
- 选用的处理冲突的方法
- hash表的饱和度,装载因子 α=n/m(n表示实际装载数据长度 m为表长)
当数据n增加时,我可以通过增加表长m,以维持装载因子不变,确保ASL不变。
删除
首先链地址法是可以直接删除元素的,但是开放定址法是不行的,拿前面的双探测再散列来说,假如我们删除了元素1,将其位置置空,那 23就永远找不到了。正确做法应该是删除之后置入一个原来不存在的数据,比如-1。
代码实现
Map中的集合,元素是成对存在的。每个元素由键与值两部分组成,通过键可以找对所对应的值。
- HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
- LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致
get() & put() & remove()
containsKey()
containsKey(key)方法是判断该key在map中是否有key存在。如果存在则返回true。如果不存在则返回false。
遍历键找值
Set<String> keySet = map.keySet();
Iterator<String> it =keySet.iterator(); //遍历存放所有key的Set集合
while(it.hasNext()){ //利用了Iterator迭代器**
//得到每一个key
String key = it.next();
//通过key获取对应的value
String value = map.get(key);
System.out.println(key+"="+value);
}
遍历键值对
//获取Map中的所有key与value的对应关系
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//遍历Set集合
Iterator<Map.Entry<String,String>> it =entrySet.iterator();
while(it.hasNext()){
//得到每一对对应关系
Map.Entry<String,String> entry = it.next();
//通过每一对对应关系获取对应的key
String key = entry.getKey();
//通过每一对对应关系获取对应的value
String value = entry.getValue();
System.out.println(key+"="+value);
}