01:哈希-启动!
两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出和为目标值 target
的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
class Solution{
public int[] two_sum(int[] nums,int target){
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length,++i){
diff = target - nums[i];
if(map.containKey(diff)) {
return new int[]{i,map.get(diff)}
}
map.put(nums[i],i);
}
return null;
}
}
字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
- 方法1
异位词按照字母顺序做排序后一定相等,所以对每一个词利用Array.sort进行排序,结果作为key,value为一个列表,存放排序后为当前key的所有词
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] chars = str.toCharArray();
Arrays.sort(chars);
String sort_str = new String(chars);
if(map.containsKey(sort_str)){
map.get(sort_str).add(str);
}else{
List list = new ArrayList<>();
list.add(str);
map.put(sort_str,list);
}
}
return new ArrayList<>(map.values());
}
}
- 方法2
字母异位词的原料一定相同,所以可以利用一个类来描述该词,即利用一个数组来存储该词的每一个字母的个数。该类可以替代方法1的key。
注意:一定要要重写equals和hashcode方法!
此方法无需对字符串进行排序,而是遍历累加,所以时间复杂度上会更优秀。
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<Word, List<String>> map = new HashMap<>();
for (String str : strs) {
Word word = new Word(str);
if(map.containsKey(word)){
map.get(word).add(str);
}else{
List list = new ArrayList<>();
list.add(str);
map.put(word,list);
}
}
return new ArrayList<>(map.values());
}
class Word{
private char[] chars = new char[26];
Word(String s){
char[] chars1 = s.toCharArray();
for (char c: chars1) {
chars[c-'a']++;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Word word = (Word) o;
return Arrays.equals(chars, word.chars);
}
@Override
public int hashCode() {
return Arrays.hashCode(chars);
}
}
}
最长连续序列
给定一个未排序的整数数组 nums(数据可重复)找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
方法:将所有元素都放进哈希表中,key是唯一标识即可(所以用hashset即可),value即为元素值,然后遍历该哈希表,假如当前遍历值为v,若哈希表中不存在v-1,则证明它是连续序列的开头,则从它开始循环查找是否存在v+1,v+2....,若存在则将当前的序列长度+1,否则跳出循环,继续遍历哈希表。
class Solution {
public int longestConsecutive(int[] nums) {
HashSet<Integer> hashset = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
hashset.add(nums[i]);
}
int count = 0;
int res = 0;
for (int v: hashset) {
if(!hashset.contains(v-1)){
count = 1;
int current = v;
while(hashset.contains(current+1)){
count++;
current++;
}
res = Math.max(count,res);
}
}
return res;
}
}
总结
哈希表主要利用空间换时间的思想
在题目中也要注意数据规模的提示
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现