给自己复盘的随想录笔记-哈希表

news2024/12/29 16:36:22

哈希表理论基础

哈希表

那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。

将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数

哈希函数

如果hashCode得到的数值大于 哈希表的大小了,也就是大于tableSize了,怎么办呢?

此时为了保证映射出来的索引数值都落在哈希表上,我们会在再次对数值做一个取模的操作,这样我们就保证了学生姓名一定可以映射到哈希表上了。

如果学生的数量大于哈希表的大小怎么办,此时就算哈希函数计算的再均匀,也避免不了会有几位学生的名字同时映射到哈希表 同一个索引下标的位置。

接下来哈希碰撞登场

哈希碰撞

一般哈希碰撞有两种解决方法, 拉链法和线性探测法。

拉链法

线性探测法 

使用线性探测法,一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题。

例如冲突的位置,放了小李,那么就向下找一个空位放置小王的信息。所以要求tableSize一定要大于dataSize ,要不然哈希表上就没有空置的位置来存放 冲突的数据了。如图所示:

常见的三种哈希结构 

当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。

  • 数组
  • set (集合)
  • map(映射)

总结

总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法

但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。

如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!

有效的字母异位词

242. 有效的字母异位词 - 力扣(LeetCode)

/**
 * 242. 有效的字母异位词 字典解法
 * 时间复杂度O(m+n) 空间复杂度O(1)
 */
class Solution {
    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];

        for (int i = 0; i < s.length(); i++) {
            record[s.charAt(i) - 'a']++;     // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
        }

        for (int i = 0; i < t.length(); i++) {
            record[t.charAt(i) - 'a']--;
        }
        
        for (int count: record) {
            if (count != 0) {               // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        }
        return true;                        // record数组所有元素都为零0,说明字符串s和t是字母异位词
    }
}

赎金信

这道题目和上一道题目很像,相当于求 字符串a 和 字符串b 是否可以相互组成 ,而这道题目是求 字符串a能否组成字符串b,而不用管字符串b 能不能组成字符串a。

本题判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成,但是这里需要注意两点。

  • 第一点“为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思”  这里说明杂志里面的字母不可重复使用。

  • 第二点 “你可以假设两个字符串均只含有小写字母。” 说明只有小写字母,这一点很重要

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        // shortcut
        if (ransomNote.length() > magazine.length()) {
            return false;
        }
        // 定义一个哈希映射数组
        int[] record = new int[26];

        // 遍历
        for(char c : magazine.toCharArray()){
            record[c - 'a'] += 1;
        }

        for(char c : ransomNote.toCharArray()){
            record[c - 'a'] -= 1;
        }
        
        // 如果数组中存在负数,说明ransomNote字符串中存在magazine中没有的字符
        for(int i : record){
            if(i < 0){
                return false;
            }
        }

        return true;
    }
}

字母异位词分组

49. 字母异位词分组 - 力扣(LeetCode)

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> m = new HashMap<>();
        for (String str : strs) {
            char[] s = str.toCharArray();
            Arrays.sort(s);
            // s 相同的字符串分到同一组
            m.computeIfAbsent(new String(s), k -> new ArrayList<>()).add(str);
        }
        return new ArrayList<>(m.values());
    }
}

  1. m.computeIfAbsent(new String(s), k -> new ArrayList<>()).add(str);: 这是computeIfAbsent方法的使用,它的作用是:

    • new String(s): 将排序后的字符数组s重新转换回字符串。
    • computeIfAbsent: 这个方法检查Map中是否存在以new String(s)为键的映射。如果不存在,它会执行提供的函数(即lambda表达式),并用该函数的结果作为值来创建新的键值对。
    • k -> new ArrayList<>(): 这是一个lambda表达式,定义了当键不存在时应该如何创建新的值。在这个例子中,它创建了一个新的ArrayList
    • .add(str): 将当前的字符串str添加到对应键的列表中。

找到字符串中所有字母异位词

解题思路:双指针

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> ans = new ArrayList<>();
        // 初始化一个数组来统计字符串 p 中每个字符的出现次数
        int[] cnt = new int[26];
        for(int i = 0; i < p.length(); i++){
            cnt[p.charAt(i) - 'a']++;
        }
        // l 和 r 分别表示滑动窗口的左右边界
        int l = 0;
        for(int r = 0; r < s.length(); r++){
            // 更新当前窗口中字符的计数数组
            cnt[s.charAt(r) - 'a']--;
            // 从左侧收缩窗口,直到当前字符的计数在限定范围内
            while(cnt[s.charAt(r) - 'a'] < 0){
                cnt[s.charAt(l) - 'a']++;
                l++;
            }
            // 检查当前窗口大小是否等于字符串 p 的大小
            if(r - l + 1 == p.length()){
                ans.add(l);
            }
        }
        return ans;
    }
}

另一个大佬把双指针相关的题目和思路总结了一遍,明明好好过一下

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2086289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Qt】QLCDNumber | QProgressBar | QCalendarWidget

文章目录 QLCDNumber —— 显示数字QLCDNumber 的属性QLCDNumber 的使用 QProgressBar —— 进度条QProgressBar 的属性创建一个进度条修改为 红色的进度条 QCalendarWidget —— 日历QCalendarWidget 的属性QCalendarWidget 的使用 QLCDNumber —— 显示数字 QLCDNumber 的属…

Nuxt3入门:介绍、项目安装和了解视图(第一节)

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 有对 Nuxt3.0 感兴趣的小伙伴吗&#xff1f;一起来了解下 一、介绍 Nuxt is an open source framework that makes web development intuitive and powerful. Create performant and production-grad…

通过 pnpm 安装依赖包会发生什么

通过 pnpm 安装依赖包会发生什么 通过 pnpm 下载的包都是放在一个全局目录&#xff08;.pnpm-store&#xff09;下&#xff0c;默认是在 ${os.homedir}/v3/.pnpm-store&#xff0c;如果我们不确定在哪里&#xff0c;可以输入下面的命令手动配置&#xff1a; pnpm set store-d…

数据库文件(嵌入式)

一、数据库文件与普通文件区别 1、普通文件对数据管理&#xff08;增删改查&#xff09;效率低 2、数据库对数据管理效率高&#xff0c;使用方便 二、常用数据库 1、关系型数据库&#xff1a; 将复杂的数据结构简化为二维表格形式 大型&#xff1a;Oracle、DB2 中型&#x…

Java 入门指南:Java NIO —— Channel(通道)

NIO 的引入 在传统的 Java I/O 模型&#xff08;BIO&#xff09;中&#xff0c;I/O 操作是以阻塞的方式进行的。当一个线程执行一个 I/O 操作时&#xff0c;它会被阻塞直到操作完成。这种阻塞模型在处理多个并发连接时可能会导致性能瓶颈&#xff0c;因为需要为每个连接创建一…

哈工大-操作系统L29

从生磁盘到文件 通过文件使用磁盘更加直观方便 一.映射的左右与实现 1.映射作用 如何从文件得到盘块号,用户看到的字符流,而操作系统看见的是盘块,所以建立字符流到盘块的映射 读写&#xff1a;电梯队列到内存缓冲区中&#xff0c;修改然后再放到电梯队列写出去 操作系统负…

web渗透:信息收集常用的工具

目录 如何根据特定网站的特性选择合适的信息收集工具&#xff1f; 网络安全专业人士通常会使用哪些信息收集工具进行漏洞挖掘&#xff1f; 数据分析师在进行市场研究时通常使用哪些信息收集工具&#xff1f; 数据收集工具 数据处理工具 数据分析工具 数据呈现工具 思维导…

艺术家林曦:“高枕无忧”的生活,需要遇见更好的自己

多年前&#xff0c;林曦老师在与朋友的交谈中&#xff0c;曾提到“想过高枕无忧的生活”。那种身心安逸、无所忧虑&#xff0c;坦然面对自己的状态&#xff0c;想来着实愉快。      或许&#xff0c;当焦虑变为当今社会难以避免的课题&#xff0c;“高枕无忧”才更成了我们…

数据结构:栈、队列详解篇

数据结构&#xff1a;栈、队列详解篇 一、栈&#xff08;一&#xff09;栈的概念&#xff08;二&#xff09;栈的实现1、结构定义2、功能实现&#xff08;1&#xff09;栈的初始化&#xff08;2&#xff09;栈的销毁&#xff08;3&#xff09;栈的扩容&#xff08;4&#xff09…

【大模型从入门到精通46】LLM部署运维(LLM Ops)使用Kubeflow Pipelines掌握LLM工作流3

这里写目录标题 功能概览函数定义实践示例&#xff1a;测试适当的拒绝最佳实践与建议适用于科学测验测试的修订函数科学测验测试函数定义执行与评估最佳实践与注意事项 功能概览 evaluate_request_refusal 函数模拟了系统应该基于预定义的标准拒绝生成测验的情景&#xff0c;这…

推荐9款AI论文写作推荐的论文指导!快速生成高质量初稿

在当前的学术写作领域&#xff0c;AI论文写作工具已经成为许多研究人员和学生的重要助手。这些工具不仅能够帮助用户快速生成高质量的论文初稿&#xff0c;还能在一定程度上简化学术写作流程&#xff0c;提高写作效率。以下是九款被广泛推荐的AI论文写作工具&#xff0c;它们各…

Docker续1:docker使用

一、打包传输 1.打包 [rootlocalhost ~]# systemctl start docker [rootlocalhost ~]# docker save -o centos.tar centos:latest [rootlocalhost ~]# ls anaconda-ks.cfg centos.tar 2.传输 [rootlocalhost ~]# scp centos.tar root192.168.1.100:/root 3.删除镜像 [r…

付费自习室管理小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商家管理&#xff0c;类型管理&#xff0c;自习室管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;自习室&#xff0c;我的 …

python-旋转木马(赛氪OJ)

[题目描述] 我们要做一个旋转木马&#xff01; 输入一个 nn 的字符矩阵&#xff0c;将其顺时针旋转 90 度后输出。输入格式&#xff1a; 输入共 n1 行。 第一行一个整数 n&#xff0c;表示矩阵大小。 接下来 n 行&#xff0c;每行一个长度为 n 的字符串&#xff0c;仅包含小写字…

Linux高性能服务器编程 总结索引 | 第2章:IP协议详解

IP头部信息 IP数据报的路由和转发 1、IP 服务的特点 1、IP 协议是 TCP/IP 协议族的动力&#xff0c;它为上层协议提供 无状态、无连接、不可靠的服务 2、无状态 是指 IP 通信双方不同步传输数据的状态信息&#xff0c;因此 所有 IP 数据报的发送、传输和接收都是相互独立、没…

【Linux应用编程实战】常见函数应用

介绍一些Linux应用编程实战遇到的&#xff0c;常见要用的函数&#xff0c;进行概况总结。 目录 main&#xff08;&#xff09; lseek&#xff08;&#xff09; poll&#xff08;&#xff09; struct pollfd 结构体返回值典例 mmap&#xff08;&#xff09; munmap&#xff08;…

kylin-麒麟操作系统-安装内存泄露补丁-以及kylin-kms-activation.service服务不断重启解决思路

文章目录 前言1. 问题现象1.1 使用journalctl命令查看更详细的日志信息 2. 解决思路2.1 思路一&#xff1a;2.2 思路二&#xff1a;2.3 合理的解法: 3. 扩展-修复内存泄露3.1 查看自己使用的镜像3.2 到麒麟官网下载相应的补丁包3.3 安装步骤3.4 重启kylin-kms-activation.servi…

python如何另起一行

python 字符串换行的三种方式&#xff1a; 第一种&#xff1a;三个单引号 print 我是一个程序员 我刚开始学习python 第二种&#xff1a;三个双引号 print """ 我是一个程序员 我刚开始学习python""" 第三种&#xff1a;\结尾 print "我是…

生成式AI,搜索赛道的又一个黄金十年

文&#xff5c;白 鸽 编&#xff5c;王一粟 随着生成式AI的发展&#xff0c;搜索引擎正在被重构&#xff0c;越来越多玩家开始布局AI搜索赛道。 一方面&#xff0c;传统搜索引擎/浏览器正借助AI技术的重构重新焕发生机&#xff0c;无论是移动端还是PC端&#xff0c;都在抢占…

GHA高质量原创文章是什么?

GHA文章是一种专为提高搜索引擎优化&#xff08;SEO&#xff09;效果而设计的高质量原创内容。GHA代表高质量&#xff0c;这些文章通过精心编写和策略布局&#xff0c;就是为了帮助网站迅速在Google等搜索引擎上获得排名&#xff0c;写一篇能在Google上获得高排名的文章&#x…