前言
- 只用Java。
1.两数之和
关键信息一句话总结:
查找补数是否出现过 -> 哈希表
- 方法1:双重for循环。
java
import java.util.Arrays;
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] ans = new int[] { 0, 0 };
for (int i = 0; i < nums.length; i++) {
int need = target - nums[i];
for ( int j = 0 ; j < i; j ++ ){
if ( need == nums[j] ){
ans[0] = j;
ans[1] = i;
}
}
}
return ans;
}
}
- 方法2:哈希表。
- 难点1:在于你能不能想到哈希表,只看题目,不要看算法标签,为什么用哈希表?
- 分析1:
哈希表用于快速通过键找到值,key -> value。那么关键就在于定义合适的key和value。好的,联想到实习的时候运用的哈希关联,用一个HashMap记录键值对,然后变多层循环为少层循环。 - 难点2:java如何实现哈希表
- 分析2:
java
Map<T, G> hashMap = new HashMap<>();
G item = hashMap.get(key);
hashMap.put(key, value);
hashMap.remove(key);
hashMap.remove(key, value);
boolean bool = hashMap.containsKey(key);
boolean bool = hashMap.containsValue(value);
hashMap.clear();
// 遍历键值对
hashMap.forEach((k, v) -> {
// doanything
});
// 遍历值
for(G each : hashMap.values()){
// doanything
}
// 遍历键
for(T each : hashMap.keySet()){
// doanything
}
- 反思:这道题是数值 -> 索引号,把target - 数字的值作为了key,索引号为value,在一次遍历的时候,因为 a + b = target, 所以target - a = b,遍历到a时判断对应的b存不存在就可以了
java
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> numMap = new HashMap<>();
// index -> value
for(int i = 0; i < nums.length; i++) {
if(numMap.containsKey(target - nums[i])) {
return new int[]{ numMap.get(target - nums[i]), i };
} else {
numMap.put(nums[i], i);
}
}
return new int[0];
}
}
49.字母异位词分组
关键信息一句话总结:
等价类分组问题 → 构造标准化 key → HashMap
- 分析1:将顺序不同的字母组成的单词归类到一起,很显然,它们在排序后的值一摸一样,所以我们要进行排序操作,然后把排序后值一样的单词归类到一起,我们使用哈希表来模拟这种操作,key为排序后的单词,value为收集的结果,如果一个单词排序后与key一致,就加入这个value,如果key不存在,就创建一个这个单词的key
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> val = map.get(key);
if(val == null) {
val = new ArrayList<>();
}
val.add(str);
// 要重新put回map 并不是修改完了就行了 因为java是值传递 不会修改原值
map.put(key, val);
}
// 创建List的方法 把map.values()转化成List即可
return new ArrayList<List<String>>(map.values());
}
}
- 反思:我没有想明白设为key合适,谁为value合适,我应该下次使用哈希的时候要想明白这个事情,何为key,何为value
128.最长连续序列
关键信息一句话总结:
利用 HashSet 快速查找 + 只从序列起点扩展 → 去重后的连续区间统计问题
- 分析:我们需要在一个乱序的数组里面找出数字连续的最长序列,且只能用一次扫描,观察到例子中有重复的元素只算一次,那么我们要先将所有数据进行去重,然后在去重后的数字里面遍历每一个数,遍历到当前数字时,判断去重后的数字里面是否有只比当前数字大1的数字,如果有,那么一直延申下去,如果没有了,不再延申,记录此时的长度与最大长度比较,长度重新计算,直到遍历完所有的元素
java
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
// 1.先放在集合里避免二次扫描时消耗时间复杂度
for(int each : nums) {
set.add(each);
}
int max = 0;
// 2.再从集合里面找
for(int num : set) {
// 这个数不存在比他小1的数 说明它就是起点
if(!set.contains(num - 1)) {
int leng = 1;
int start = num;
// 3.一直延申出去
while(set.contains(start + 1)) {
leng++;
start++;
}
max = Math.max(leng, max);
}
}
return max;
}
}
- 反思:要善于观察,一步一步抽丝剥茧,而不是一上来就用哈希,这道题其实没用哈希,用了集合去重和简单查找