算法——哈希表

哈希表简介

**是什么:**存储数据的容器
有什么用:快速查找某个元素,时间复杂度O(1),空间复杂度O(n)
**什么时候使用哈希表:**频繁查找某一个数(这里不要忘了之前的二分,时间复杂度O(logN))
怎么用哈希表: 1.容器 2.用数组模拟简易哈希表image.png

两数之和

两数之和

题目解析

  • 该数组中找出 **和为目标值 **target 的那 两个 整数,并返回它们的数组下标。
  • 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
  • 按任意顺序返回答案

算法原理

解法一:暴力解法
之前的枚举是,固定一个指针,向后移动另一个指针开始遍历,直到找到目标值。这次枚举我们依然先固定一个指针,然后遍历这个数之前的数字,遍历完仍然向后移动另一个指针。时间复杂度O(n2)image.png

解法二:使用哈希表优化
暴力解法遍历指针之前的数字所消耗的时间复杂度是O(n),如果我们将所要遍历的数字放到哈希表里,那我们的就只需要花费O(1)的时间复杂度就能够找到。总体时间复杂度消耗为O(n),空间复杂度也为O(n);典型的空间换时间。在哈希表里存储的是数字和下标一起绑定存储
image.png

为什么之前的遍历不好用呢?
把数组全放入哈希表中时,如果我们所要找的数和自身相等时,那就会找到自身,这是不符合题意的。这种情况是需要特判的。但我们运用上面的的哈希表做优化就不会遇到这种边界问题。
image.png

代码实现

class Solution 
{
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        unordered_map<int, int> hash; // <nums[i], i>
        for(int i = 0; i < nums.size(); i++)
        {
            int x = target - nums[i];
            if(hash.count(x)) return {hash[x], i};
            hash[nums[i]] = i;
        }
        
// 照顾编译器,返回无效值
        return {-1, -1};
    }
};

判定是否为字符重排

判断是否为字符重排

题目解析

给定两个由小写字母组成的字符串 s1 和 s2
其中一个字符串的字符重新排列后,能否变成另一个字符串。
image.png

算法原理

解法一:模拟:将字符串所有组成可能性全部列出来,然后进行比较。但是时间复杂度是指数级别的,非常恐怖
解法二:哈希表: 如果s1能够重排s2,那么每个字符出现的次数肯定相同。那么我们可以使用哈希表,但是我们是使用容器还是使用数组模拟呢。如果使用容器,要找hash1里字符的int和hash2里对应字符的int进行比较,较为麻烦。因为题目中说了只由小写字母组成,image.png

**优化:只使用一个哈希表:**只用一个哈希表记录s1字符出现的次数,然后遍历s2,s2中出现的字符在hash1中减掉1即可。当两个字符串的⻓度不相等的时候,是不可能构成互相重排的,直接返回false

代码实现

class Solution 
{
public:
    bool CheckPermutation(string s1, string s2) 
    {
        if(s1.size() != s2.size()) return false;
        int hash[26] = { 0 };
// 先统计第⼀个字符串的信息
    for(auto ch : s1)
    hash[ch - 'a']++;

// 扫描第⼆个字符串,看看是否能重排
    for(auto ch : s2)
    {
    //a映射到字符下标为0,所以-‘a’
    hash[ch - 'a']--;
    if(hash[ch - 'a'] < 0) return false;
    }

    return true;
    }
};

存在重复元素I

存在重复元素I

题目解析

如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

算法原理

和两数之和相同,固定一个数,找在他之前的数有没有出现重复。这里我们的hash表只需要存一个k值就行

代码实现

class Solution 
{
public:
    bool containsDuplicate(vector<int>& nums) 
    {
    unordered_set<int> hash;
    for(auto x : nums)
        if(hash.count(x)) return true;
        else hash.insert(x);
    return false;
    }
};

存在重复元素II

存在重复元素II

题目解析

判断数组中是否存在两个 不同的索引_ i 和 _j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k
image.png

算法原理

解法:哈希表
表里存储字符和下标,将数组中的数字和其对应的下标一起绑定存入hash表中。开始移动。当发现前面由相同元素时,将两个下标相减,发现不符合条件,将1(紫色指针所指的)放入hash表中,此时存入的<1,3>就把最开始的<1,0>覆盖掉了。继续向后移动。当移动到下一个1时,只需要考虑里第三个1最近位置的1(即第二个1)即可。因为如果最远位置的符合条件(第一个1),那么近的位置也符合。image.png

思考题:如果数组内存在⼤量的「重复元素」,⽽我们判断下标所对应的元素是否符合条件的时候,需要将不同下标的元素作⽐较,怎么处理这个情况呢?

答:这⾥运⽤了⼀个「⼩贪⼼」。我们按照下标「从⼩到⼤」的顺序遍历数组,当遇到两个元素相同,并且⽐较它们的下标时,这两个下标⼀定是距离最近的,因为:
• 如果当前判断符合条件直接返回 true ,⽆需继续往后查找。
• 如果不符合条件,那么前⼀个下标⼀定不可能与后续相同元素的下标匹配(因为下标在逐渐变⼤),那么我们可以⼤胆舍去前⼀个存储的下标,转⽽将其换成新的下标,继续匹配

代码实现

class Solution 
{
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) 
    {
    unordered_map<int, int> hash;
    for(int i = 0; i < nums.size(); i++)
    {
        if(hash.count(nums[i]))
        {
          if(i - hash[nums[i]] <= k) return true;
        }

    hash[nums[i]] = i;
    }
    return false;
    }
};

字母异位词分组

字母异位词分组

题目解析

  • 判断字母异位词,并且按组返回image.png

算法原理

解法:哈希表

  1. 判断两个字符串是否为字母异位词:我们可以用哈希表判断,这里我们使用排序,虽然这样时间复杂度更高,但是代码好写一些。按照ASCII码值排序
  2. 如何分组:借助容器,我们将k值定位为string,Value值定义为字符串数组string(K-V)。遍历第一个字符串eat,按照ASCII码值排序之后为aet,这里作为k值的string,然后将原始数组中的字符串开始作为V值遍历比较。将eat排完序后发现hash表里由aet,存入,然后继续向后遍历。若发现排序完之后没有,创建一个新的(如ant)再继续比较image.png

代码实现

class Solution 
{
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) 
    {
        unordered_map<string, vector<string>> hash;
    // 1. 把所有的字⺟异位词分组
    for(auto& s : strs)
    {
    string tmp = s;
    sort(tmp.begin(), tmp.end());
    hash[tmp].push_back(s);
    }

// 2. 结果提取出来
    vector<vector<string>> ret;
    for(auto& [x, y] : hash)
    {
        ret.push_back(y);
    }

    return ret;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

sqlilabs第三十二三十三关

Less-32&#xff08;GET - Bypass custom filter adding slashes to dangerous chars) 手工注入 由 宽字符注入可知payload 成功触发报错 http://192.168.21.149/Less-32/ ?id1%df 要写字符串的话直接吧字符串变成ascii码 注意16进制的表示方式 自动注入 sqlmap -u http:…

三相电机转差率为负值的情形

1.电机开始发电的特征 注意&#xff0c;电机因为有输入频率对原始旋转磁场的影响&#xff0c;在正常工作时&#xff0c;应该处于稳态&#xff0c;因为旋转磁场决定了这个系统的运转方向和运转的大致频率区间。它会处于力矩平衡态。但是&#xff0c;如果&#xff0c;此时电机处…

智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.指数分布算法4.实验参数设定5.算法结果6.…

《Halcon 100项目-2》Halcon查找零件个数

Halcon查找零件个数 read_image (Image20231225201927, D:/image/bilibili/photo/屏幕截图 2023-12-25 201927.png) rgb1_to_gray (Image20231225201927, GrayImage)threshold (GrayImage, Region, 0, 128) draw_rectangle1 (200000, Row1, Column1, Row2, Column2) gen_recta…

redis基本用法学习(C#调用StackExchange.Redis操作redis)

StackExchange.Redis是基于C#的高性能通用redis操作客户端&#xff0c;也属于常用的redis客户端之一&#xff0c;本文学习其基本用法。   新建Winform项目&#xff0c;在Nuget包管理器中搜索并安装StackExchange.Redis&#xff0c;如下图所示&#xff1a;   StackExchange.…

ElasticSearch 使用映射定义索引结构

动态映射 dynamic 可选值解释true默认值&#xff0c;启用动态映射&#xff0c;新增的字段会添加到映射中runtime查询时动态添加到映射中false禁用动态映射&#xff0c;忽略未知字段strict发现未知字段&#xff0c;抛出异常 显示映射 创建映射 PUT user {"mappings&qu…

sql_lab之sqli注入中的cookie注入

Cookei注入&#xff08;gxa的从cookei注入&#xff09; 1.打开控制台 2.验证id2时的值 document.cookie"id2" 3.判断是上面闭合方式 document.cookie"id2 -- s" 有回显 说明是’单引号闭合 4.用order by 判断字段数 5.用联合查询判断回显点 接下来的…

C语言 指针

C语言学习&#xff01; 目录 文章目录 前言 一、指针是什么&#xff1f; 二、指针变量的大小 三、指针和指针类型 四、指针和函数 五、野指针 5.1野指针成因 5.2 如何规避野指针 六、指针运算 6.1 指针- 整数 6.2 指针-指针 6.3 指针的关系运算 总结 前言 指针理解的2个要点&a…

(2023|CVPR,Corgi,偏移扩散,参数高斯分布,弥合差距)用于文本到图像生成的偏移扩散

Shifted Diffusion for Text-to-image Generation 公众&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 2. 方法 2.1 偏移扩散 3. 实验 3.1 无监督文本到图像生成 3.2 无…

IDEA Maven Helper插件 解决jar冲突

Jar包冲突报错 程序抛出java.lang.ClassNotFoundException异常&#xff1b; 程序抛出java.lang.NoSuchMethodError异常&#xff1b; 程序抛出java.lang.NoClassDefFoundError异常&#xff1b; 程序抛出java.lang.LinkageError异常等&#xff1b;Maven Jar包管理机制 在Maven项…

设计模式--工厂方法模式

实验3&#xff1a;工厂方法模式 本次实验属于模仿型实验&#xff0c;通过本次实验学生将掌握以下内容&#xff1a; 1、理解工厂方法模式的动机&#xff0c;掌握该模式的结构&#xff1b; 2、能够利用工厂方法模式解决实际问题。 [实验任务]&#xff1a;加密算法 目前常用…

数据库管理-第127期 LSM Tree(202301225)

数据库管理-第127期 LSM Tree&#xff08;202301225&#xff09; 说起分布式数据库&#xff0c;绕不开的一个话题就是LSM Tree&#xff0c;全称为log-structured merge-tree&#xff0c;回到吕海波老师授权过的那句话“没搞过Oracle的&#xff0c;但又是数据库圈里的人&#x…

《我在北京送快递》平凡隽永的时刻,对人生更具意义

《我在北京送快递》平凡隽永的时刻&#xff0c;对人生更具意义 胡安焉 文章目录 《我在北京送快递》平凡隽永的时刻&#xff0c;对人生更具意义[toc]摘录感悟 摘录 转“没有期限的承诺无疑就是委婉的拒绝” 转书友&#xff1a;亨利福特说&#xff0c;我聘的是一双手&#xff0…

基于 FFmpeg 的跨平台视频播放器简明教程(十二):Android SurfaceView 显示图片和播放视频

系列文章目录 基于 FFmpeg 的跨平台视频播放器简明教程&#xff08;一&#xff09;&#xff1a;FFMPEG Conan 环境集成基于 FFmpeg 的跨平台视频播放器简明教程&#xff08;二&#xff09;&#xff1a;基础知识和解封装&#xff08;demux&#xff09;基于 FFmpeg 的跨平台视频…

LeetCode-回文链表(234)

题目描述&#xff1a; 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 因为这一题是受到876题求链表中间节点的启发&#xff0c;所以在这里也加一下。 876.链表的中间结点…

格密码:傅里叶矩阵

目录 一. 铺垫性介绍 1.1 傅里叶级数 1.2 傅里叶矩阵的来源 二. 格基与傅里叶矩阵 2.1 傅里叶矩阵详细解释 2.2 格基与傅里叶矩阵 写在前面&#xff1a;有关傅里叶变换的解释太多了&#xff0c;这篇博客主要总结傅里叶矩阵在格密码中的运用。对于有一定傅里叶变换基础的同…

python 解决手机拍的书籍图片发灰的问题

老师给发的作业经常是手机拍的&#xff0c;而不是扫描&#xff0c;背景发灰&#xff0c;如果二次打印就没有看了&#xff0c;象这样&#xff1a; 如果使用photoshop 处理&#xff0c;有些地方还是扣不干净&#xff0c;不如python 做的好&#xff0c;处理后如下&#xff1a; 具体…

一个基于多接口的业务自动化测试框架!

这是一个成熟的框架&#xff0c;不是要让别人当小白鼠&#xff0c;它已经先后在两家公司的5条业务线进行了推广应用&#xff0c;用例条数到了几千条以上&#xff0c;并且从2018年开始每天都在CI/CD流程中被调用执行。 已有那么多接口测试框架&#xff0c;为什么重复造轮子&…

详解Java反射机制reflect(一学就会,通俗易懂)

1.定义 #2. 获取Class对象的三种方式 sout(c1)结果为class com.itheima.d2_reflect.TestClass 获取到了Class对象就相当于获取到了该类 2.获取类的构造器 3.获取全部构造器对象 2.根据参数类型获取构造器对象 类型后必须加.class 3.构造器对象调用构造器方法 4.暴力访问 4.获…

11-GraalVM元原生时代的Java虚拟机

文章目录 GraalVM诞生的背景Java在微服务/云原生时代的困境事实矛盾 问题根源Java离不开虚拟机 解决方案革命派保守派 GraalVM入门GraalVM特征GraalVM下载和安装GraalVM下载win10安装及配置linux安装及配置 GraalVM初体验(Linux)多语言开发(了解即可、官网有Demo)GraalCompiler…