【算法刷题之哈希表篇(1)】

news2024/9/25 3:17:39

目录

  • 1.哈希表基础理论
  • 2.leetcode-242. 有效的字母异位词
    • (1)方法一:排序
    • (2)方法二:哈希表
  • 3.leetcode-349. 两个数组的交集
    • (1)方法一:哈希表
    • (2)方法二:排序 + 双指针
  • 3.leetcode-202. 快乐数
    • (1)方法一:快慢指针
    • (2)方法二:哈希表
  • 4.leetcode-1. 两数之和

1.哈希表基础理论

哈希表是根据关键码的值而直接进行访问的数据结构。
哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:
在这里插入图片描述
那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。

例如要查询一个名字是否在这所学校里。

要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1)就可以做到。

我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。

将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数。
哈希函数
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里了。

哈希函数如下图所示,通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。
在这里插入图片描述
在这里插入图片描述
常见的三种哈希结构
当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。
数组
set (集合)
map(映射)
可以去看看我的stl详解,其中有详细讲解

2.leetcode-242. 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
在这里插入图片描述

(1)方法一:排序

t 是 s 的异位词等价于「两个字符串排序后相等」。因此我们可以对字符串 s 和 t 分别排序,看排序后的字符串是否相等即可判断。此外,如果 s 和 t的长度不同,t 必然不是 s 的异位词。

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size()!=t.size())
        {
            return false;
        }
        sort(s.begin(),s.end());
        sort(t.begin(),t.end());
        return s==t;
    }
};

(2)方法二:哈希表

t 是 s 的异位词等价于「两个字符串中字符出现的种类和次数均相等」。由于字符串只包含 26个小写字母,因此我们可以维护一个长度为 26 的频次数组 table,先遍历记录字符串 s 中字符出现的频次,然后遍历字符串 t,减去 table中对应的频次,如果出现 table[i]<0,则说明 t 包含一个不在 s 中的额外字符,返回 false 即可。

class Solution {
public:
    bool isAnagram(string s, string t) {
        if (s.length() != t.length()) {
            return false;
        }
        vector<int> table(26, 0);
        for (auto& ch: s) {
            table[ch - 'a']++;
        }
        for (auto& ch: t) {
            table[ch - 'a']--;
            if (table[ch - 'a'] < 0) {
                return false;
            }
        }
        return true;
    }
};

3.leetcode-349. 两个数组的交集

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
在这里插入图片描述

(1)方法一:哈希表

计算两个数组的交集,直观的方法是遍历数组 nums1,对于其中的每个元素,遍历数组 nums2 判断该元素是否在数组 nums2 中,如果存在,则将该元素添加到返回值。假设数组 nums1 和 nums2 的长度分别是 m 和 n,则遍历数组 nums1 需要 O(m)的时间,判断 nums1 中的每个元素是否在数组 nums2 中需要 O(n) 的时间,因此总时间复杂度是 O(mn)。

如果使用哈希集合存储元素,则可以在 O(1) 的时间内判断一个元素是否在集合中,从而降低时间复杂度。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> set1, set2;
        for (auto& num : nums1) {
            set1.insert(num);
        }
        for (auto& num : nums2) {
            set2.insert(num);
        }
        return getIntersection(set1, set2);
    }

    vector<int> getIntersection(unordered_set<int>& set1, unordered_set<int>& set2) {
        vector<int> intersection;
        for (auto& num : set1) {
            if (set2.count(num)) {
                intersection.push_back(num);
            }
        }
        return intersection;
    }
};

(2)方法二:排序 + 双指针

1.首先对两个数组进行排序,然后使用两个指针遍历两个数组。
2.可以预见的是加入答案的数组的元素一定是递增的
3.初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        int length1 = nums1.size(), length2 = nums2.size();
        int index1 = 0, index2 = 0;
        vector<int> intersection;
        while (index1 < length1 && index2 < length2) {
            int num1 = nums1[index1], num2 = nums2[index2];
            if (num1 == num2) {
                // 保证加入元素的唯一性
                if (!intersection.size() || num1 != intersection.back()) {
                    intersection.push_back(num1);
                }
                index1++;
                index2++;
            } else if (num1 < num2) {
                index1++;
            } else {
                index2++;
            }
        }
        return intersection;
    }
};

3.leetcode-202. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
在这里插入图片描述

(1)方法一:快慢指针

在这里插入图片描述

如图所示:如果不是快乐数也会进入循环,所以用快慢指针来判断,如果会相遇,且相遇时不是1,则不是快乐数。

class Solution {
public:
    int bitSquareSum(int n) {
        int sum = 0;
        while(n > 0)
        {
            int bit = n % 10;
            sum += bit * bit;
            n = n / 10;
        }
        return sum;
    }
    
    bool isHappy(int n) {
        int slow = n, fast = n;
        do{
            slow = bitSquareSum(slow);
            fast = bitSquareSum(fast);
            fast = bitSquareSum(fast);
        }while(slow != fast);
        
        return slow == 1;
    }
};

(2)方法二:哈希表

题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!

正如:关于哈希表,你该了解这些! (opens new window)中所说,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。判断sum是否重复出现就可以使用unordered_set。

class Solution {
public:
    int GetSum(int n)
    {
        int sum=0;
        while(n>0)
        {
            sum+=(n%10)*(n%10);
            n=n/10;
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> set;
        while(1)
        {
            int sum=GetSum(n);
            if(sum==1)
            {
                return true;
            }
            else if(set.count(sum))
            {
                return false;
            }
            else{
                set.insert(sum);
            }
            n=sum;
        } 
    }
};

4.leetcode-1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。
在这里插入图片描述
map中key和value分别表示什么。

这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。

那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。

所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        unordered_map<int,int> map;
        for(int i=0;i<nums.size();++i)
        {
            auto iter=map.find(target-nums[i]);
            if(iter!=map.end())
            {
                return {iter->second,i};
            }
            else
            {
                map.insert(pair<int,int> {nums[i],i});
            }
        }
        return {};
    }
};

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

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

相关文章

脚本掌控,Linux上实现Spring Boot(JAR包)开机自启

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; 脚本掌控&#xff0c;Linux上实现Spring Boot&#xff08;JAR包&#x…

智能综合性公共系统安防监控系统项目建设方案

一、系统概述 智能综合性公共系统安防监控系统是为了保障公共系统的安全而设计的一套综合性的安防解决方案。该系统集成了多种先进的技术和设备&#xff0c;以实现对系统内部和周围环境的全方位、高效率的监控和管理。智能综合性公共系统安防监控系统旨在提供全面、高效的安全保…

冠达管理大盘分析:光伏板块震荡走高,钧达股份涨停

光伏板块24日盘中震动走高&#xff0c;到发稿&#xff0c;时创动力大涨超16%&#xff0c;钧达股份涨停&#xff0c;昱能科技涨超8%&#xff0c;阿特斯、晶澳科技、阳光电源等涨超5%&#xff0c;隆基绿能涨近4%。 东研山私募证券投资&#xff08;百度搜索冠达管理)基金管理有限公…

用心维护好电脑,提高学习工作效率

无论是学习还是工作&#xff0c;电脑都是IT人必不可少的重要武器&#xff0c;一台好电脑除了自身配置要经得起考验&#xff0c;后期主人对它的维护也是决定它寿命的重要因素&#xff01; 一、我的电脑 系统制造商: ASUSTeK COMPUTER INC. 系统型号: ZenBook UX481FAY 1.1 如…

Docker创建Consul并添加权限控制

一、部署Consul 1、拉取镜像&#xff1a; docker pull consul:<consul-version> 2、运行 docker run --name consul1 -p 8300:8300/tcp -p 8301:8301/tcp -p 8301:8301/udp -p 8302:8302/tcp -p 8302:8302/udp -p 8500:8500 -p 8600:8600/tcp -p 8600:8600/udp -v /h…

Mybatis引入与使用

一、新建项目 使用IDEA&#xff0c;新建项目 注意&#xff1a;这里创建的是Maven项目 二、数据准备 因为Mybatis是操作数据库的框架&#xff0c;需要操作数据库&#xff0c;这里我们选用Mysql数据库&#xff0c;使用数据库脚本初始化一下数据。 -- 如果数据库不存在则创建数…

8.23笔记(手写),deeplabV2与V3

空洞卷积(Dilated convolution)如下图所示&#xff0c;其中 r 表示两列之间的距离(r1就是常规卷积了)。 池化可以扩大感受野&#xff0c;降低数据维度&#xff0c;减少计算量&#xff0c;但是会损失信息&#xff0c;对于语义分割来说&#xff0c;这造成了发展瓶颈。 空洞卷积可…

Python实战之如何用Python创建并训练自己的聊天机器人详解

你是否想过拥有一个自己的聊天机器人&#xff0c;让它陪伴你聊天、解答问题&#xff1f;Python可以帮助你实现&#xff01;在本文中&#xff0c;我们将介绍如何使用Python创建自己的聊天机器人。 第一步&#xff1a;安装必要的库 在使用Python创建聊天机器人之前&#xff0c;你…

python按日期生成文件夹并保存图片

背景说明&#xff1a; 在做一个瑕疵检测项目的时候&#xff0c;模型需要实时处理摄像头获取的图像进行处理&#xff0c;然后进行OK和NG判别&#xff0c;对于判别的结果要分别保存在不同的文件夹中&#xff0c;同时需要保证图片具有可区分性 。 分析&#xff1a; 考虑使用pat…

谈谈智能交通的概念

目录 1.什么是智能交通 2.智能交通的应用场景 1.智能公交车 2.共享单车 3.汽车联网 4.智慧停车 1.什么是智能交通 智能交通是指运用信息技术和通信技术等现代技术手段&#xff0c;对交通运输系统进行智能化的管理和优化&#xff0c;以提高交通效率、安全性和环境友好性的一…

上门服务系统|上门服务小程序如何提升生活质量?

上门服务其实就是本地生活服务的升级&#xff0c;上门服务包含很多行业可以做的。例如&#xff1a;厨师上门、上门家电维修、跑腿等等。如今各类本地化生活服务越来越受大家的喜爱。基于此市场愿景&#xff0c;我们来谈谈上门服务系统功能。 一、上门服务系统功能 1、预约服务…

eCharts热力图Y轴左上角少一块

问题&#xff1a; 如图 在图例的左上角 Y轴会少一块 官方demo https://echarts.apache.org/examples/zh/editor.html?cheatmap-cartesian 事实上 把官方demo的左上角坐标 [ 6, 0, 1 ] 修改为 [ 6, 0, 0 ] 后 依旧会出现该问题 查遍文档 并无解释 也没有任何配置项可解决…

shell 06(shell内置命令)

一、内置命令介绍 shell 内置命令&#xff0c;就是由 Bash shell 自身提供的命令&#xff0c;而不是文件系统中的可执行文件 使用type 来确定一个命令是否是内置命令: type 命令 通常来说&#xff0c;内置命令会比外部命令执行得更快: 执行外部命令时不但会触发磁盘 I/0&am…

vue中form、table和input标签过长

form标签过长 效果&#xff1a; 代码&#xff1a; <el-form-item v-for"(item,index) in ticketEditTable1" :label"item.fieldNameCn" :propitem.fieldName :key"item.fieldNameCn" overflow"":rules"form[item.fieldName…

组队buff,citywalk,同学走起

本文关键词 组队、旅游、打比赛、动心 南京、成都、西安、北京、烟火气 梧桐杯、大数据、创新、得行 ...... 这里是第三届中国移动“梧桐杯”大数据创新大赛&#xff0c; 只接受在校大学生报名。 这里是五阶赛程三阶有奖的比赛&#xff0c; 百万奖金池&#xff0c;下饺子…

神通数据库v7.0试用版安装步骤

网上找了下神通数据库的安装教程&#xff0c;发现都已经过时&#xff0c;或者安装受阻&#xff0c;于是直接从官网下载后尝试亲自安装了一遍适用版&#xff0c;在CentOS7(64bit)环境具体操作步骤如下&#xff1a; 1、安装 wget工具 yum install -y wget 2、安装rar解压工具 …

ChatGPT多开分销版系统,完整版手把手详细教程,保姆级教程

教程方法在文末&#xff5e; 课程目录 一、课前准备 1.认识系统.mp4 2.获取本次应用的三种渠道.mp4 二、微信服务号的申请&#xff08;有就直接跳过&#xff09; 03.流程详解.mp4 04.服务号的注册.mp4 05.认证流程.mp4 06.微信支付申请与关联.mp4 三、对接千梦众筹系统…

flutter 雷达图

通过CustomPainter自定义雷达图 效果如下 主要代码 import package:flutter/material.dart; import dart:math; import dash_painter.dart; import model/charts_model.dart;class RadarChart extends StatelessWidget {final List<ChartModel> list;final double maxV…

微短剧赛道风口下的一站式点播解决方案

微短剧行业正风生水起。 一种全新的剧集模式正迅速崛起&#xff0c;并引起广泛关注。 从线下电影院的“巨幕”到PC端“网络大电影”&#xff0c;从“长视频”再到如今移动端1-3分钟的“微短剧”&#xff0c;影视行业在过去几年经历了一场深刻又显著的变化。 微短剧&#xff0…

【2023中国算力大会】《关于促进全国一体化算力网络国家枢纽节点宁夏枢纽建设若干政策的意见》解读

为加快人工智能的发展&#xff0c;丰富算力基础设施&#xff0c;推进算力赋能应用&#xff0c;强化绿电保障支持&#xff0c;构建算力产业体系&#xff0c;打造西部地区算力经济发展新高地。 对数据中心重大基础设施建设&#xff0c;每年安排专项债券资金给予支持&#xff0c;…