算法思想总结:哈希表

一、哈希表剖析

1、哈希表底层:通过对C++的学习,我们知道STL中哈希表底层是用的链地址法封装的开散列

2、哈希表作用:存储数据的容器,插入、删除、搜索的时间复杂度都是O(1),无序。

3、什么时候使用哈希表:需要频繁查找数据的场景。

4、OJ中如何使用哈希表???

(1)STL中的容器(适用所有场景,比如字符串相关、数据映射下标)

(2)数组模拟简易哈希表(减小时间损耗,容器的封装有一定代价)—>大多以下两种情况适用

情况1:(char)涉及到字符串中的“字符” ,hash[26]可以映射所有的字母。

情况2:(int)数据范围较小的时候

二、两数之和

. - 力扣(LeetCode)

解法2代码: 

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target){unordered_map<int,int> hash; //数值和下标的映射关系int n=nums.size();for(int i=0;i<n;++i){int x=target-nums[i];if(hash.count(x)) return {hash[x],i};hash[nums[i]]=i;}return {-1,-1};}
};

 三、判定是否互为字符重排

. - 力扣(LeetCode)

 解法2代码:

class Solution {
public:bool CheckPermutation(string s1, string s2) {//小优化if(s1.size()!=s2.size()) return false;//用哈希表int hash[26]={0};for(char&ch:s1) ++hash[ch-'a'];//检测第二个数组for(char&ch:s2)  if(--hash[ch-'a']<0)  return false;return true;}
};

四、存在重复元素I

. - 力扣(LeetCode)

解法2代码:

class Solution {
public:bool containsDuplicate(vector<int>& nums) {unordered_set<int> hash; //有负数,所以必须用库里面的哈希表for(auto&e:nums) if(hash.count(e)) return true;else hash.insert(e);return false;}
};

 五、存在重复元素II

. - 力扣(LeetCode)

解法1代码:

class Solution {
public:bool containsNearbyDuplicate(vector<int>& nums, int k) {unordered_map<int,size_t> hash;//数值和下标的映射size_t n=nums.size();for(size_t i=0;i<n;++i){//如果哈希表中有这个数if(hash.count(nums[i])&&i-hash[nums[i]]<=k) return true;hash[nums[i]]=i;//存下标的映射}return false;}
};

解法2代码:

class Solution {
public:bool containsNearbyDuplicate(vector<int>& nums, int k) {//滑动窗口解题,让set始终保存着k个元素,如果发现了区间内有重复元素,那么就可以返回trueunordered_set<int> s;size_t n=nums.size();for(size_t i=0;i<n;++i){if(s.count(nums[i])) return true;s.emplace(nums[i]);//不断将数字丢进去if(i>=k) s.erase(nums[i-k]); //窗口超出区间了,就将最前面那个给删掉}return false;}
};

六、存在重复元素III(经典)

. - 力扣(LeetCode)

 解法1代码:

class Solution {
public://绝对值尽量拆解掉//滑动窗口解决问题(控制区间)  需要支持插入、查找、删除  尽可能有序 set//k是下标的差值  t是元素的差值bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {//lower_bound 利用二分找到第一个>=num的迭代器 降序就是<=//upper_bound 利用二分找到第一个>num的迭代器  降序就是<set<long> s;//需要一个有序集合for(size_t i=0;i<nums.size();++i){ //在下标范围为 [max(0,i−k),i] 内找到值范围在 [u−t,u+t]的数。set<long>::iterator it=s.lower_bound((long)nums[i]-t);if(it!=s.end()&&*it<=(long)nums[i]+t) return true;s.insert(nums[i]);if(i>=k)  s.erase(nums[i - k]);}return false;}
};

 思路2:分桶(非常精巧的思路)

思路来源:. - 力扣(LeetCode)分桶思路详细讲解

     因为这个思路来源写得非常的详细,所以直接看就行,以往我们的分桶,更多的是针对整数的分桶,但是在该题中,扩展了存在负数的时候如何分桶,保证每个桶内的元素个数是一样的。这是一种非常巧妙的方法!!!要结合具体的实例去看!!

核心思路:保证每个桶内的绝对值相差小于t,k个桶。当我们遍历到这个数的时候,如果对应的桶的存在,就是true,如果相邻桶存在,看看差值是否符合要求。每个桶中只会有一个元素,因为有多的我们就会直接返回结果。

class Solution {
public:int getid(long u,long t){return u>=0?u/(t+1):(u+1)/(t+1)-1;}bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {//桶排序   size_t n=nums.size();//分成k个桶  每个桶的大小是t+1 (0,1,2,3) ->保证一个桶里面是符合的unordered_map<int,int> hash;  //第一个是存id  第二个是存元素for(size_t i=0;i<n;++i){long u=nums[i];int id= getid(u,t); //找编号//看看当前桶存不存在if(hash.count(id)) return true;//看看相邻桶在不在,如果在的话 就看看差值if(  hash.count(id-1)&&u-hash[id-1]<=t||hash.count(id+1)&&hash[id+1]-u<=t) return true;if(i>=k) hash.erase(getid(nums[i-k],t));//桶数多了,就去掉一个hash[id]=u;//开新的桶}return false;}
};

七、字母异位词分组(经典)

. - 力扣(LeetCode)

class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {//字母异位词->排序后都是相同的unordered_map<string,vector<string>> hash; //将异位词绑定起来for(auto&s:strs){string temp=s;sort(temp.begin(),temp.end());hash[temp].emplace_back(s);}//提取出来vector<vector<string>> ret;for(auto&[x,y]:hash)  ret.emplace_back(y); //取哈希表中键值对的方法C++14支持//for(auto&kv:hash)  ret.push_back(kv.second);return ret;}
};

八、前K个高频单词(经典)

 . - 力扣(LeetCode)

解法1:map+vector+稳定排序+lambda优化
          map的底层是红黑树,插入的时候map<string,int> 会按照字典序排好,而我们现在要按照出现次序去排序,同时对于出现次数相同的保证字典序在前面,所以我们其中之一的策略就是vector+sort ,但是sort底层是快排,并不具备稳定性,但是库里面有一个stable_sort是稳定的排序

class Solution {
public:typedef pair<string,int> PSI;vector<string> topKFrequent(vector<string>& words, int k) {map<string,int> countmap;//计数for(auto&s:words) ++countmap[s];//此时已经按照字典序排好了,将其拷贝到vector中vector<PSI> nums(countmap.begin(),countmap.end());//要用一个稳定的排序 我们排序的是比较value,所以要修改比较逻辑stable_sort(nums.begin(),nums.end(),[](const PSI&kv1,const PSI&kv2) {return kv1.second>kv2.second;});vector<string> ret(k);for(int i=0;i<k;++i)  ret[i]=nums[i].first;return ret;}
};

解法2:unordered_map+vector+sort+调整比较逻辑+lambda优化 

class Solution {
public:typedef pair<string,int> PSI;vector<string> topKFrequent(vector<string>& words, int k) {unordered_map<string,int> countmap;//计数for(auto&s:words) ++countmap[s];//此时已经按照字典序排好了,将其拷贝到vector中vector<PSI> nums(countmap.begin(),countmap.end());//要用一个稳定的排序 我们排序的是比较value,所以要修改比较逻辑sort(nums.begin(),nums.end(),[](const PSI&kv1,const PSI&kv2){ return kv1.second>kv2.second||(kv1.second==kv2.second&&kv1.first<kv2.first);});vector<string> ret(k);for(int i=0;i<k;++i)  ret[i]=nums[i].first;return ret;}
};

上面两种解法都是借助vector容器+sort去解决的。

 解法3:unordered_map+priority_queue+compare类

class Solution {
public:typedef pair<string,int> PSI;struct compare//要注意仿函数要+const修饰,否则可能编译不过{bool operator()(const PSI&kv1,const PSI&kv2) const{if(kv1.second==kv2.second) return kv1.first<kv2.first;return kv1.second>kv2.second;}};vector<string> topKFrequent(vector<string>& words, int k) {unordered_map<string,int> countmap;//计数for(auto&s:words) ++countmap[s];//丢到优先级队列里priority_queue<PSI,vector<PSI>,compare> heap;for (auto& it : countmap) {heap.push(it);if (heap.size() > k) heap.pop();}vector<string> ret(k);for(int i=k-1;i>=0;--i) {ret[i]=heap.top().first;heap.pop();}return ret;}
};

 解法4:unordered_map+multiset+compare类

class Solution {
public:typedef pair<string,int> PSI;struct compare//要注意仿函数要+const修饰,否则可能编译不过{bool operator()(const PSI&kv1,const PSI&kv2) const{return kv1.second>kv2.second||(kv1.second==kv2.second&&kv1.first<kv2.first);}};vector<string> topKFrequent(vector<string>& words, int k) {unordered_map<string,int> countmap;//计数for(auto&s:words) ++countmap[s];multiset<PSI,compare> sortmap(countmap.begin(),countmap.end());vector<string> ret(k);multiset<PSI,compare>::iterator it=sortmap.begin();size_t i=0;while(k--) {ret[i++]=it->first;++it;}return ret;}
};

 解法5:map+multimap+compare类(能过 但这是巧合)

       这题能过的原因是map实现了字典序的排序。而底层的multimap封装中对于相同的键值是优先插入到其右侧。

class Solution {
public:struct compare//要注意仿函数要+const修饰,否则可能编译不过{bool operator()(const int&k1,const int&k2) const{return k1>k2;}};vector<string> topKFrequent(vector<string>& words, int k) {map<string,int> countmap;//计数for(auto&s:words) ++countmap[s];multimap<int,string,compare> sortmap;for(auto &kv:countmap) sortmap.insert(make_pair(kv.second,kv.first));vector<string> ret(k);auto it=sortmap.begin();size_t i=0;while(k--) {ret[i++]=it->second;++it;}return ret;}
};

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

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

相关文章

低功耗蓝牙模块在便携式医疗设备上的应用前景

随着科技的不断发展&#xff0c;医疗设备的便携性和智能化已经成为了一种趋势。在这个背景下&#xff0c;低功耗蓝牙模块(Bluetooth Low Energy,简称BLE)作为一种先进的无线通信技术&#xff0c;正逐渐在便携式医疗设备中发挥着越来越重要的作用。本文美迅物联网MesoonRF将探讨…

TiKV学习5:TiDB SQL执行流程

目录 1. DML语句读流程概要 2. DML语句写流程概要 3. DDL 流程概要 4. SQL的Parse和Compile 5. 读取的执行 6. 写入的执行 7. DDL的执行 8. 小结 1. DML语句读流程概要 TiDB Server接收sql并处理&#xff0c;TiKV负责持久化数据&#xff0c;PD提供TSO和Region的数据字典…

HackTheBox-Machines--Bashed

Bashed 测试过程 1 信息收集 NMAP 80 端口 目录扫描 http://10.129.155.171/dev/phpbash.min.php http://10.129.155.171/dev/phpbash.php 半交互式 shell 转向 交互式shell python -c import socket,subprocess,os;ssocket.socket(socket.AF_INET,socket.SOCK_STREAM);s.co…

优化CPU占用率及内存占用2

在标准化无线通信板时&#xff0c;关注过程序占用ram的问题&#xff0c;当时 发现每一个线程都会分配8M栈空间&#xff0c;这次换rk3568后&#xff0c;偶尔看了下RAM占用&#xff0c;吓了一跳&#xff0c;不但每个线程有8M栈空间&#xff0c;几乎每个线程都占用了64MB的一个RAM…

AOP进阶

黑马程序员JavaWeb开发教程 文章目录 一、通知类型1.1 通知类型1.2 注意事项1.3 PointCut 二、通知顺序2.1 执行顺序 三、切入点表达式3.1 切入点表达式3.2 切入点表达式-execution3.2 切入点表达式- annotation 四、连接点4.1 连接点 一、通知类型 1.1 通知类型 Around&…

部署专属网页版ChatGPT-Next-Web

背景 工作学习中经常使用chat-gpt, 需求是多端使用gpt问答&#xff0c;因此搭建一个网页版本方便多个平台使用。最后选择了 ChatGPT-Next-Web 部署说明 一键部署自己的web页面&#xff0c;因为是使用免费的vercel托管的&#xff0c;vercel节点在全球都有&#xff0c;理论上突…

oracle 12c DB卸载流程

1.运行卸载程序 [rootprimary1 ~]# su - oracle [oracleprimary1 ~]$ cd $ORACLE_HOME/deinstall [oracleprimary1 deinstall]$ ./deinstall Checking for required files and bootstrapping ... Please wait ... 这里选择3 、回车、y、y、回车、ASM 这里输入y 2.删除相关目录…

Midjourney应用:电商模特换装

今天我们应用的是Midjourney应用&#xff1a;电商模特换装 网上找到一件衣服&#xff0c;没有模特 方法一&#xff1a;两图片融合&#xff0c;BLEND命令&#xff0c;效果不是很理想失真 方法二&#xff1a;服装图片垫图说明细节缺失https://cdn.discordapp.com/attachments/1…

Iphone自动化指令每隔固定天数打开闹钟关闭闹钟(一)

注意&#xff1a;因为是第一次用iphone的快捷指令&#xff0c;不是很明白&#xff0c;所以之后多次运行发现有bug&#xff0c;所以快捷指令部分在下一章重新写&#xff0c;我用两个日期测试了&#xff0c;没问题&#xff0c;这一章可以当做熟悉快捷指令的一些操作用&#xff0c…

STM32高级控制定时器之输入捕获模式

目录 概述 1 输入捕获模式 1.1 原理介绍 1.2 实现步骤 1.3 发生输入捕获流程 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM调制占空比函数 3.2 应用函数库 4 测试 4.1 功能框图 4.2 运行结果 源代码下载地址&#xf…

【Word】调整列表符号与后续文本的间距

1. 默认的列表格式&#xff1a; 2. 修改间距&#xff1a; ************************************************** 分割线 ************************************************************ 3. 效果

推荐一款开源电子签章/电子合同系统

文章目录 前言一、项目介绍二、项目地址三、技术架构四、代码结构介绍五、功能模块六、功能界面首页面手写签名面板电子印章制作数字证书生成 总结 前言 大家好&#xff01;我是智航云科技&#xff0c;今天为大家分享一个免费开源的电子签字系统。 一、项目介绍 开放签电子签…

热门新游 2024 植物大战僵尸杂交版 Mac 版本下载安装详细教程

最近植物大战僵尸杂交版可谓是非常的火&#xff0c;好多主播都在播这款游戏&#xff0c;我一个 Mac 党也想玩&#xff0c;可奈何该游戏目前只有 PC 版本&#xff0c;经过一番折腾终于在我的 Mac 上安装上了该游戏&#xff0c;分享给大家 其实安装过程也很简单&#xff0c;只需…

AI视频下载:ChatGPT数据科学与机器学习课程

ChatGPT是一个基于OpenAI开发的GPT-3.5架构的AI对话代理。作为一种语言模型,ChatGPT能够理解并对各种主题生成类似人类的响应,使其成为聊天机器人开发、客户服务和内容创作的多用途工具。 此外,ChatGPT被设计为高度可扩展和可定制的,允许开发人员对其响应进行微调并将其集成到…

数组的应用-24点游戏

目录 24点游戏 游戏规则 游戏主要分为三部分 电脑出牌 用户输入算式 电脑判断胜负 总结 24点游戏 游戏规则&#xff1a; 54张扑克抽出大小王&#xff0c;剩余52张用来用于游戏&#xff1b;每一轮从52张牌中随机抽出4张&#xff1b;玩家运用加&#xff0c;减&#xff0…

JUC常见类

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f649; 内容推荐:Java锁的策略&#x1f649; &#x1f439;今日诗词:苟利国家生死以,岂因祸福避趋之&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&#x1f64…

Windows系统WDS+MDT网络启动自动化安装

Windows系统WDS+MDT网络启动自动化安装 适用于在Windows系统上WDS+MDT网络启动自动化安装 1. 安装准备 1.下载windows server 2019、windows 10 pro的ISO文件,并安装好windows server 2019 2.下载windows 10 2004版ADK及镜像包 1.1 安装平台 Windows 111.2. 软件信息 软件…

模型优化——模型剪枝、模型量化、知识蒸馏

1.模型剪枝 1.1什么是模型剪枝&#xff1f; 深度学习网络模型从卷积层到全连接层存在着大量冗余的参数&#xff0c;大量神经元激活值趋近于0&#xff0c;将这些神经元去除后可以表现出同样的模型表达能力&#xff0c;这种情况被称为过参数化&#xff0c;而对应的技术则被称为模…

摸鱼大数据——select查询7-10

7、union联合查询 union: 对重复数据会去重 union all: 对重复数据不会去重 ​ 注意&#xff1a;union和union all中两边的字段&#xff08;类型、顺序&#xff09;要对应上 示例: use day08; select * from students; ​ select id,name from students where id in (95001,9…

Python中的 Lambda 函数

大家好&#xff0c;在 Python 编程的世界里&#xff0c;有一种功能强大却不常被提及的工具&#xff0c;它就是 Lambda 函数。这种匿名函数在 Python 中拥有着令人惊叹的灵活性和简洁性&#xff0c;却常常被许多开发者忽视或者只是将其当作一种附加功能。Lambda 函数的引入&…