什么时候使用哈希法,当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
HashMap<key,value> HashSet<key>
HashMap适用于需要存储键值对,并且需要通过键进行查找和访问值的场景。HashSet适用于需要存储唯一元素,并且不需要通过键进行访问的场景。
1 两数之和 +
使用nSum超出时间限制
map是一种key value的存储结构,可以用key保存数值,用value再保存数值所在的下标。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res=new int[2];//结果数组:都是下标
Map<Integer,Integer> map=new HashMap<>();
//key: temp数组中的值 value :对应下标
for(int i=0;i<nums.length;i++){
int temp=target-nums[i]; // 遍历当前元素,并在map中寻找是否有匹配的key
if(map.containsKey(temp)){
res[1]=i; //当前元素索引
res[0]=map.get(temp); //差值元素值的下标
//满足判断条件,并在循环中需要跳出循环
break;
}
map.put(nums[i],i); // 如果没找到匹配对,就把访问过的元素和下标加入到map中 值作为key
}
return res;
}
}
49 字母异位词分组 (处理字符:标准化)+
由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键。
List<String> :一个字符串列表
char[] array = str.toCharArray(); 将当前字符串转换为字符数组
List是接口,不能直接实例化,需要使用常见实现类 ArrayList、LinkedLis
Map 接口是Java中用于表示键值对映射的接口。
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// 创建一个哈希表,用于存储分组后的字母异位词
Map<String, List<String>> map = new HashMap<>();
// 遍历给定的字符串数组
for (String str : strs) {
// 将当前字符串转换为字符数组,并对字符数组进行排序
char[] array = str.toCharArray();
Arrays.sort(array);
// 将排序后的字符数组转换为字符串,作为哈希表的键
String key = new String(array);
// 在哈希表中查找以当前键为索引的列表,如果不存在则创建一个新的列表
List<String> list = map.getOrDefault(key, new ArrayList<String>());
// 将当前字符串添加到对应的列表中
list.add(str);
// 将更新后的列表存回哈希表
map.put(key, list);
}
// 返回哈希表中的所有值,即分组后的字母异位词列表
return new ArrayList<List<String>>(map.values());
}
}
128 最长连续序列 + (先找开头元素,然后递增) Hashset
这道题最直接的想法就是排序,排序之后连续的序列就很容易找到了。不过排序的时间复杂度是 O(NlogN),而题目要求我们时间复杂度为 O(N),这就得另想办法了。
想找连续序列,首先要找到这个连续序列的开头元素,然后递增,看看之后有多少个元素还在 nums 中,即可得到最长连续序列的长度了。
我们可以用空间换时间的思路,把数组元素放到哈希集合里面,然后去寻找连续序列的第一个元素,即可在 O(N) 时间找到答案。
class Solution {
public int longestConsecutive(int[] nums) {
// 转化成哈希集合,方便快速查找是否存在某个元素
HashSet<Integer> set = new HashSet<Integer>();
//将数组值放入集合中
for (int num : nums) {
set.add(num);
}
//序列数不连续,只查找是不是存在
int res = 0;
for (int num : set) {
if (set.contains(num - 1)) {
// num 不是连续子序列的第一个,跳过
continue;
}
// num 是连续子序列的第一个,开始向上计算连续子序列的长度
int curNum = num;
int curLen = 1;
while (set.contains(curNum + 1)) {
curNum += 1;
curLen += 1;
}
// 更新最长连续序列的长度
res = Math.max(res, curLen);
}
return res;
}
}