算法——哈希表

news2024/11/16 13:23:40

哈希表简介

**是什么:**存储数据的容器
有什么用:快速查找某个元素,时间复杂度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;
    }
};

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

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

相关文章

论文阅读:Large Language Models Are Zero-Shot Time Series Forecasters(2023NIPS)

摘要 文章涉及了两个时间序列的任务&#xff1a;forecasting&#xff0c;imputation. 对于预测任务&#xff1a;通过将时间序列编码为一系列数字&#xff0c;可以将时间序列预测任务转化为文本里面的next-token预测任务。在大规模预训练语言模型的基础上&#xff0c;文章提出了…

泰迪智能科技分享:AI大模型发展趋势分析

大规模预训练语言模型&#xff0c;也被称为“大模型”或“基座模型”&#xff0c;其特点在于拥有巨大的参数量&#xff0c;构成了复杂的人工神经网络模型。大模型具有规模性&#xff08;参数量大&#xff09;、涌现性&#xff08;产生预料之外的新能力&#xff09;以及通用性&a…

k8s二进制最终部署(网络 负载均衡和master高可用)

k8s中的通信模式 1、pod内部之间容器与容器之间的通信&#xff0c;在同一个pod 中的容器共享资源和网络&#xff0c;使用同一个网络命名空间&#xff0c;可以直接通信的 2、同一个node节点之内&#xff0c;不同pod之间的通信&#xff0c;每个pod都有一个全局的真实的IP地址&a…

最新国内使用GPT4教程,GPT语音对话使用,Midjourney绘画,ChatFile文档对话总结+DALL-E3文生图

一、前言 ChatGPT3.5、GPT4.0、GPT语音对话、Midjourney绘画&#xff0c;文档对话总结DALL-E3文生图&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和…

ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

目录 ​专题一 开启大模型 专题二 基于ChatGPT大模型提问框架 专题三 基于ChatGPT大模型的数据清洗 专题四 基于ChatGPT大模型的统计分析 专题五 基于ChatGPT大模型的机器学习 专题六 基于ChatGPT大模型的科研绘图 专题七 基于ChatGPT大模型的GIS应用 专题八 基于基于C…

k8s集群etcd备份与恢复

一、前言 k8s集群使用etcd集群存储数据&#xff0c;如果etcd集群崩溃了&#xff0c;k8s集群的数据就会全部丢失&#xff0c;所以需要日常进行etcd集群数据的备份&#xff0c;预防etcd集群崩溃后可以使用数据备份进行恢复&#xff0c;也可用于重建k8s集群进行数据恢复 二、备份…

[C/C++]排序算法 快速排序 (递归与非递归)

目录 &#x1f6a9;概念: &#x1f6a9;实现: ⚡1.hoare ⚡2.挖坑法 ⚡3.双指针法 &#x1f6a9;快速排序递归实现 &#x1f6a9;快速排序非递归实现 &#x1f6a9;概念: 通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据比另一部分的所有…

华为OD机试真题-手机App防沉迷系统-2023年OD统一考试(C卷)

题目描述&#xff1a; 智能手机方便了我们生活的同时&#xff0c;也侵占了我们不少的时间。“手机App防沉迷系统”能够让我们每天合理的规划手机App使用时间&#xff0c;在正确的时间做正确的事。 它的大概原理是这样的&#xff1a; 1、在一天24小时内&#xff0c;可注册每个Ap…

什么洗地机值得推荐?2024入门级智能洗地机

对于当代社畜&#xff0c;每天下班后回家已经疲惫不堪&#xff0c;但家务活仍然等待着处理。虽然外卖可以解决洗碗的问题&#xff0c;但地面的清洁却是无法回避的任务。传统的扫地、拖地流程让人感到腰酸背痛&#xff0c;因此人们纷纷寻找能够快速清洁地面的工具&#xff0c;如…

Shell命令与Linux操作系统:深入理解其原理和功能(2/2)

在当今数字化时代&#xff0c;操作系统的安全性和稳定性对于个人用户和企业都至关重要。Linux&#xff0c;作为一个广泛使用的操作系统&#xff0c;其强大的文件权限系统是保护系统安全的核心机制之一。无论是在服务器管理、软件开发还是日常使用中&#xff0c;有效地管理和理解…

scons_交叉编译arm64_sysroot基于根文件rootfs编译方法

文章目录 1.问题现象2.环境变量3.实例1:交编译arm64 hello.c解决方法1: 指定rootfs下的include头文件解决方法2: 下载开源arm64-linux-gnu-gcc小结 4.交叉编译依赖第3方库1.前言2.小知识: gcc默认搜索与支持的库3.实例: 交叉编译依赖ROS的程序gcc/g 编译流程gcc/g 链接流程 5.遇…

阿里云双11活动:如何通过客户端连接linux服务器?配置入门详解

前言 最近双11活动&#xff0c;发现阿里云有服务器活动&#xff0c;就买了一个&#xff0c;今天主要给大家介绍下&#xff0c;如何通过通过客户端进行连接linux服务器后&#xff0c;进行简单的操作。 配置服务器信息 打开浏览器登录到阿里云服务器页面上&#xff0c;找到个人…

uni-app/vue封装etc车牌照输入,获取键盘按键键值

先看下效果如下&#xff1a; 动态图如下 uniapp的keyup获取不到keyCode和compositionstart&#xff0c;compositionend&#xff0c;所以需要监听input节点的keyup事件&#xff0c; 思路以及代码如下&#xff1a; 1.将每一个字符用文本框输入&#xff0c;代码如下 <view …

ClickHouse基础知识(二):ClickHouse 安装教程

1. 准备工作 1.1 确定防火墙处于关闭状态 1.2 CentOS 取消打开文件数限制 &#xff08;1&#xff09;在 hadoop101 的 /etc/security/limits.conf 文件的末尾加入以下内容 sudo vim /etc/security/limits.conf&#xff08;2&#xff09;在 hadoop101 的/etc/security/limits.…

64.乐理基础-打拍子-前八后十六、前十六后八拍子

前置内容&#xff1a;63.乐理基础-打拍子-四十六-CSDN博客 前八后十六指的是前半拍是一个八分音符&#xff0c;后半怕是两个十六分音符的节奏型&#xff0c;如图1。 前十六后八刚好就与前八后十六反着&#xff0c;如图3。 图1&#xff1a;在以四分音符为一拍的时候这三个音符加…

Android下载gradle失败解决方法

1、在gradle-wrapper.properties文件中查看自己需要下载gradle什么版本的包和zip路径&#xff08;wrapper/dists&#xff09;。 2、在setting中查看Gradle的保存路径&#xff0c;如下图&#xff1a;C:/Users/Administrator/.gradle&#xff0c;加上第一步的zip路径得到下载grad…

chcp 65001

chcp 65001 DOS,BAT,CMD乱码 转UTF-8&#xff0c;就不会汉字乱码了 936 GBK 65001 UTF-8

C语言中关于if else的理解

if else我们可以理解为 if(条件1) //如果条件1成立 语句1&#xff1b; //执行语句1 else //如果条件1不成立 语句2; //执行语句2 这是一个经典的if els…

Vue Echarts 多折线图只有一条X轴(合并X轴数据并去重排序) - 附完整示例

echarts&#xff1a;一个基于 JavaScript 的开源可视化图表库。 目录 效果 一、介绍 1、官方文档&#xff1a;Apache ECharts 2、官方示例 二、准备工作 1、安装依赖包 2、示例版本 三、使用步骤 1、在单页面引入 echarts 2、指定容器并设置容器宽高 3、数据处理&am…

Word中插入mathtype的行内公式显示不全,设置行距,最小值

Word中插入mathtype的行内公式显示不全 如下图&#xff1a;公式上下被遮住 解决方式&#xff1a; 设置所在段落的行距&#xff1a;最小值--xx磅。同时取消勾选 “如果定义了文档网格&#xff0c;则对齐到网格” 处理后效果&#xff1a;