有序集合(映射)容器一般基于平衡二叉搜素树实现,无序集合(映射)容器则一般基于哈希表实现。
哈希表,是数组基于某种映射规则(函数)的⼀种扩展:
- 外部表现为
hash_table['key'] = value
,直接通过关键字(浮点数,字符串甚至结构体)索引 - 内部实现为
linear_list[hash(key)] = value
,依靠哈希函数把复杂信息映射到一个较小的值域,并作为索引
哈希函数设计得越好,数据分布越均匀,碰撞概率越小。理想情况下,哈希表的插入、查询
、删除时间复杂度均为\(O(1)\)。所以,当我们遇到了要快速判断一个元素是否出现集合里
的问题,就可以考虑哈希法。
题目 | 思路 | 备注 |
---|---|---|
383. 赎金信 | 字符统计|hash(char)=char-'a' |
等价于判断两个字符统计表是否相等 |
349. 两个数组的交集 | 对集合\(B\)元素,查询是否也存在于\(A\) | 注意不要一边访问一边删除,HashSet |
202. 快乐数 | 模拟,查询是否运算陷入无限死循环 | 另一个检测环的方式是快慢指针 |
1. 两数之和 | 在\(x\)前,查询是否存在值\(target-x\) | 下标作为附加信息需要存储,HashMap |
874. 模拟行走机器人 | 模拟,查询当前格点是否属于障碍物 | 哈希设计;地图方向数组 |
49. 字母异位词分组 | 字母基元 -> 异位词列表 | 分组和哈希冲突“挂链”的相似性;哈希设计 |
30. 串联所有单词的子串
暴力
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> ans=new ArrayList<>();
int tot=0;
for(String word:words){
tot+=word.length();
}
for(int i=0;i+tot<=s.length();i++){
String str=s.substring(i,i+tot);
if(validate(str,words)) ans.add(i);
}
return ans;
}
boolean validate(String str, String[] words){
int k=words[0].length();
HashMap<String, Integer> splitWords=new HashMap<>();
for(int i=0;i<str.length();i+=k){
String key=str.substring(i,i+k);
if(splitWords.get(key)!=null){
splitWords.put(key,splitWords.get(key)+1);
}
else splitWords.put(key,1);
}
for(String word:words){
Integer count=splitWords.get(word);
if(count==null) return false;
else splitWords.put(word,splitWords.get(word)-1);
}
for(String key:splitWords.keySet()){
if(splitWords.get(key)!=0) return false;
}
return true;
}
}