【力扣hot100】哈希表专题——从两数之和到最长连续序列

哈希专题的本质

把"查找问题"转换成"空间存储问题"

文章目录

题目解析

1. 两数之和

1. 两数之和

暴力
java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        for(int i = 0;i < nums.length - 1;i++){
            for(int j = i + 1;j < nums.length;j++){
                if(nums[i] + nums[j] == target){
                    return new int[]{i,j};
                }
            }
        }
        return new int[0];
    }
    
}
哈希表法
  • 在遍历同时记录一些信息,用来省去一层循环,以"空间换时间"
  • 需要记录已经遍历过的数值和它所对应的下标,可以查找表实现
  • 查找表的带两个常用实现:哈希表和平衡二叉搜索树
法一
java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int len = nums.length;
        Map<Integer,Integer> hm = new HashMap<Integer,Integer>();
        for(int i=0;i<len;i++){
            if(hm.containsKey(target - nums[i])){
                return new int[]{hm.get(target - nums[i]),i};
            }
            hm.put(nums[i],i);
        }
        return new int[0];
    }
}
法二

先创建一个哈希表

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        Map<Integer,Integer> hm = new HashMap<Integer,Integer>();
        for(int i = 0;i < nums.length;i++){
            hm.put(nums[i],i);
        }
        for(int j = 0;j < nums.length;j++){
            Integer diff = target - nums[j];
            if(hm.containsKey(diff) && hm.get(diff) != j){
                res[0] = j;
                res[1] = hm.get(diff);
                return res;
            }
        }
        return res;
    }
}

49. 字母异位词分组

49. 字母异位词分组

排序

关键:所有异位词排序后都会得到相同的字符串

java 复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<String,List<String>>();
        for (String str : strs) {
            char[] array = str.toCharArray();//String不能排序,转换成字符数组再排序
            Arrays.sort(array);
            String key = new String(array);
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            //从map中获取key对应的值;如果key不存在,就返回一个"默认值"------这里是一个新的空ArrayList<String>;如果key已存在,返回对应的List<String>
            list.add(str);
            map.put(key, list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

128. 最长连续序列

128. 最长连续序列

哈希

每个数都判断一次这个数是不是连续序列的开头那个数

  • 用哈希表查找这个数前面一个数是否存在,即num-1在序列中是否存在。存在那这个数肯定不是开头,直接跳过。
  • 因此只需要对每个开头的数进行循环,直到这个序列不再连续,因此复杂度是O(n)
java 复制代码
class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> num_set = new HashSet<Integer>();
        for(int num : nums){
            num_set.add(num);
        }

        int ans = 0;
        for(int num : num_set){
            if(!num_set.contains(num - 1)){ //判断这个数是否是开头 是则继续
                int temp_num = num;
                int temp_long = 1;

                while(num_set.contains(temp_num + 1)){
                    temp_num += 1;
                    temp_long += 1;
                }//统计由这个数开头的最长序列

                ans = Math.max(ans,temp_long);
            }
        }

        return ans;
    }
}

知识点总结

List(有序,可重复)

ArrayList
  • 底层:数组
  • 特点:查询快(O(1)),增删慢(中间插入/删除要移动元素,O(n))
  • 适用场景读多写少,比如存一组配置、查列表
LinkedList
  • 底层:双向链表
  • 特点:增删快(O(1)),查询慢(要遍历,O(n))
  • 适用场景频繁在头尾增删,比如队列、消息队列

实际开发中 90% 的情况用 ArrayList,LinkedList 很少用。


Set(无序,不可重复)

HashSet
  • 底层:HashMap
  • 特点:无序,增删查都是 O(1)
  • 适用场景去重 + 快速判断元素是否存在,比如判断用户是否已登录、判断数字是否出现过(你刚才那道题就是)
LinkedHashSet
  • 底层:LinkedHashMap
  • 特点保持插入顺序,其余和 HashSet 一样
  • 适用场景:去重 + 需要保持插入顺序
TreeSet
  • 底层:红黑树
  • 特点自动排序,O(log n)
  • 适用场景 :需要去重 + 排序,比如排行榜、Top K

Map(键值对,Key 不可重复)

HashMap
  • 底层:数组 + 链表 + 红黑树
  • 特点:无序,增删查 O(1),允许 null key 和 null value
  • 适用场景最常用的 Map,缓存、分组、计数等,比如你刚才那道题用 HashMap 分组
LinkedHashMap
  • 底层:LinkedHashMap
  • 特点保持插入顺序(或访问顺序),其余和 HashMap 一样
  • 适用场景:需要保持顺序的键值对,比如 LRU 缓存
TreeMap
  • 底层:红黑树
  • 特点按 Key 自动排序,O(log n)
  • 适用场景 :需要按 Key 排序,比如按时间排序的事件、区间查询

一张图总结

集合 底层 有序 可重复 线程安全 典型场景
ArrayList 数组 ✅ 插入顺序 列表展示、读多写少
LinkedList 双向链表 ✅ 插入顺序 队列、频繁增删
HashSet HashMap 去重、快速查找
LinkedHashSet LinkedHashMap ✅ 插入顺序 去重 + 保序
TreeSet 红黑树 ✅ 排序 去重 + 排序
HashMap 数组+链表+红黑树 Key ❌ 最常用,分组/缓存/计数
LinkedHashMap 同上+双向链表 ✅ 插入顺序 Key ❌ 保序键值对、LRU
TreeMap 红黑树 ✅ 按Key排序 Key ❌ 按Key排序、区间查询

怎么选(速查)

需求 用什么
只是存一组数据,按顺序遍历 ArrayList
去重 HashSet
去重 + 排序 TreeSet
去重 + 保持插入顺序 LinkedHashSet
键值对,最常用 HashMap
键值对 + 按 Key 排序 TreeMap
键值对 + 保持插入顺序 LinkedHashMap
多线程环境 ConcurrentHashMap(替代 HashMap)

一句话记忆

List 管顺序,Set 管去重,Map 管映射。默认都用 Hash 系列,需要排序换 Tree,需要保序换 Linked。
接下来一个月会持续更新算法题和八股面试题,欢迎大家一起学习进步

相关推荐
观远数据1 小时前
云原生BI的战略价值:不是技术选择,而是业务弹性的决定因素
java·人工智能·云原生
Full Stack Developme1 小时前
Tomcat 设计原理
java·tomcat
gongzhxu1 小时前
JetBrains IDEA开发环境搭建
java·ide·intellij-idea
程序员三明治2 小时前
【AI】RAG 生成阶段的最后一公里:Prompt 设计、幻觉抑制与引用对齐
java·人工智能·ai·大模型·llm·prompt·rag
小保CPP2 小时前
OpenCV C++基于极值区域滤波算法的场景文本检测(OCR)
c++·人工智能·opencv·算法·计算机视觉·ocr
Bug收容所2 小时前
12305项目学习day5
java·spring boot·redis·mysql·spring·rocketmq
::呵呵哒::2 小时前
java中SseEmitter
java·开发语言
lichuangcsdn2 小时前
【Spring AI 学习(三)】实现简单的对话
java·人工智能·学习·spring·spring ai
长不胖的路人甲2 小时前
Spring Bean 完整生命周期
java·spring·rpc