最近在“哈希”这两个字上吃了很多亏,原因是一直没有系统的整理下该方面的知识点,于是在此整理一下,若有不正确之处,欢迎指正!
哈希可以分为两种角度来解释:密码学的角度、算法优化的角度,两种角度略有不同,具体如下:
哈希的基本定义如下:
基本知识(来自百度百科):
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
冲突:
其实就是将任意长度的输入转换为固定长度的输入,但是既然压缩了空间就会导致一个问题:冲突,即key1≠key2,而f(key1)=f(key2),处理这种问题的基本方法有两种:线性开型寻址散列和链表散列。
散列函数:
散列函数有:1.除法散列法(除留余数法) 2.乘法散列法(平方取中法) 3.全域散列等。
一开始接触这个概念是在密码学的角度上接触的,当时讲的比较多的也是具体的应用,如MD5加密、数字签名之类的。
但是,现在很多的时候提到的哈希是指的算法应用上的角度,比如用哈希函数作为算法映射,在O(1)的时间内找到某数据。(当时面试官让我解释一下什么是哈希,我提到了它包含key和value,然后面试官想了想开玩笑似的告诉我说还是再好好看看吧,现在想想就特别委屈,我估计他是站在了密码学的角度来问我,而我是站在算法应用的角度来解释的)。好了,话归正题,站在算法优化的角度上来看,如java中的HashMap和Hashtable即是应用于如此,可以用put(key,value)方法在O(1)的时间内来建立映射,修改value,也可以用get(key)方法在O(1)的时间内来获得value,以此来避免花费O(n)时间来遍历数组。(顺便提一句,HashMap和Hashtable的区别也是面试的时候经常提到的一个问题。)
算法优化角度的应用:
如一道《编程之美》上的题目:“能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的数字n。”(百度面试的时候特别喜欢出这类题型)
比较优化的一个解法就用到了哈希:
遍历该数组,建立一个哈希表(需要O(n)时间和空间),然后在O(1)时间内就可以查找到n-arr[i]是否存在在这哈希表中即可。