本节介绍哈希表 ,主要应用于:需要在一个集合中快速查找一个元素是否存在 。一般使用的数据结构为:数组、set、map ; 数组 即为利用下标快速访问元素的天然哈希表 ;set 与 map 两个容器类型比较相似,set 是只存储关键字作为元素 ,map 是将关键字作为 key, 关键字的值 作为 value , 将这一对 作为一个元素进行存储。
242.有效的字母异位词
LeetCode-242-题目链接 由于仅包含小写字母,字母的ascii码又是连续的,所以将出现过的字母与第一个字母’a’做差,即可得到新的不重复标识,将此标识作为数组下标,对第一个字符串出现过的元素次数进行存储。然后对第二个出现过的元素按照次数进行相减,若数组全部为0,则两者为字母异位词。
class Solution {
public :
bool isAnagram ( string s, string t) {
int hash[ 26 ] = { 0 } ;
for ( int i = 0 ; i < s. size ( ) ; i++ ) {
hash[ s[ i] - 'a' ] ++ ;
}
for ( int i = 0 ; i < t. size ( ) ; i++ ) {
hash[ t[ i] - 'a' ] -- ;
}
for ( int i = 0 ; i < 26 ; i++ ) {
if ( hash[ i] != 0 ) return false ;
}
return true ;
}
} ;
349. 两个数组的交集
LeetCode-349-题目链接 由于题目中的数组长度做了限定:<1000,因此可以使用数组。 注:因为数组申请的是连续存储空间,存在最大申请的限制,一般一次性不能申请过大,所以在哈希值比较小、而且范围也比较小的情况下,可以用数组。但是如果哈希值比较少、比较分散、跨度比较大,使用数组就会造成空间的浪费。 对于本题而言,无论使用数组还是set,两者思路一样:即将第一个数组存到哈希表里(数组 or set),然后判断第二个数组中的元素是否在该哈希表里,如果在即将该元素存在一个新的哈希表(unordered_set)里,由于使用的哈希表为:unordered_set,会自动去重。
使用数组
class Solution {
public :
vector< int > intersection ( vector< int > & nums1, vector< int > & nums2) {
unordered_set< int > result;
int hash[ 1001 ] = { 0 } ;
for ( int i = 0 ; i < nums1. size ( ) ; i++ ) {
hash[ nums1[ i] ] = 1 ;
}
for ( int i = 0 ; i < nums2. size ( ) ; i++ ) {
if ( hash[ nums2[ i] ] == 1 ) {
result. insert ( nums2[ i] ) ;
}
}
return vector < int > ( result. begin ( ) , result. end ( ) ) ;
}
} ;
使用set
class Solution {
public :
vector< int > intersection ( vector< int > & nums1, vector< int > & nums2) {
unordered_set< int > result1;
unordered_set< int > result2;
for ( int i = 0 ; i < nums1. size ( ) ; i++ ) {
result1. insert ( nums1[ i] ) ;
}
for ( int i = 0 ; i < nums2. size ( ) ; i++ ) {
if ( result1. find ( nums2[ i] ) != result1. end ( ) ) {
result2. insert ( nums2[ i] ) ;
}
}
return vector < int > ( result2. begin ( ) , result2. end ( ) ) ;
}
} ;
202. 快乐数
LeetCode-202-题目链接 该题需要注意,如果不是快乐数的话,就会无限循环,因为n是有限的,它的每个位置上的数字的平方和也是有限的,所以可以判断只有当某一个求和的值重复出现时,才会陷入无限循环。 该题即可转化为,将n的各个位置平方和存到哈希表里(set),每计算一次,从哈希表里面看是否存在,有的话,就会陷入无限循环,即不是快乐数,否则即为快乐数。
class Solution {
public :
bool isHappy ( int n) {
unordered_set< int > result;
if ( n == 1 ) return true ;
while ( n != 1 ) {
result. insert ( n) ;
n = calSquare ( n) ;
if ( result. find ( n) != result. end ( ) ) {
return false ;
}
}
return true ;
}
int calSquare ( int n) {
int sum = 0 ;
while ( n > 0 ) {
sum += ( n % 10 ) * ( n % 10 ) ;
n /= 10 ;
}
return sum;
}
} ;
1. 两数之和
LeetCode-1-题目链接 因为该题最终需要返回的是所需元素的下标,是一对值,所以使用map; 该题的思路:将给定的数组的(元素,下标)逐个放入哈希表(map)中,每放入一个,计算目标值与元素差值是否在map中出现过,出现过即返回两者下标。 为啥用数组中的元素作为map的key值,是因为查找的就是元素。
class Solution {
public :
vector< int > twoSum ( vector< int > & nums, int target) {
unordered_map< int , int > numsMap;
int delta;
for ( int i = 0 ; i < nums. size ( ) ; i++ ) {
delta = target - nums[ i] ;
if ( numsMap. find ( delta) != numsMap. end ( ) ) {
return { numsMap[ delta] , i} ;
}
numsMap. insert ( { nums[ i] , i} ) ;
}
return { } ;
}
} ;