代码随想录刷题题Day5

news2024/11/14 6:12:35

刷题的第五天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀
刷题语言:C++ / Python
Day5 任务
● 哈希表理论基础
● 242.有效的字母异位词
● 349. 两个数组的交集
● 202. 快乐数
● 1. 两数之和

1 哈希表理论基础

当我们遇到要快速判断一个元素是否出现在集合里,就要考虑哈希法
哈希表:根据关键码的值而直接进行访问的数据结构(和数组根据索引下标查找的原理一样)
(1)哈希函数
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里

哈希函数通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字
在这里插入图片描述

如果hashCode得到的数值大于哈希表的大小,为了保证映射出来的索引数值都落在哈希表上,会在再次对数值做一个取模的操作,就保证了学生姓名一定可以映射到哈希表上。

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

(2)哈希碰撞
在这里插入图片描述
两种解决办法:拉链法线性探测法
拉链法:
在这里插入图片描述

位置发生冲突,将发生冲突的元素存储在链表中,就可以通过索引找到小李、小王

拉链法就是要选择适当的哈希表的大小,既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间

线性探测法:
在这里插入图片描述
使用该方法的前提:保证tableSize大于dataSize,依靠哈希表的空位解决碰撞问题
(3)常见的三种哈希结构
使用哈希法来解决问题,一般选择如下三种数据结构:

(1)数组
(2)set (集合)
(3)map(映射)

在C++中,set提供以下三种数据结构,底层实现以及优劣如下表所示
在这里插入图片描述

std::unordered_set底层实现是哈希表,std::set和std::multiset底层实现是红黑树,红黑树是平衡二叉搜索树,所以key值有序,但key值不可修改,只能删除和增加

map提供以下三种数据结构,其底层实现以及优劣如下表所示
在这里插入图片描述

std::unordered_map底层实现为哈希表,std::map 和std::multimap的底层实现是红黑树,同理,std::map 和std::multimap 的key也是有序的

使用集合解决哈希问题时,优先使用unordered_set,因为查询和增删效率最优

如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset

map是key-value的数据结构,map中,对key有限制,对value没有限制,因为key的存储方式使用红黑树实现

虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,std::set、std::multiset 使用红黑树来索引和存储,不过给我们的使用方式,还是哈希法的使用方式,即key和value。所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法,map也是相同的道理

遇到了快速判断一个元素是否出现在集合里,就是使用哈希法

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

2 有效的字母异位词

本道题可以感受到数组用来做哈希表带来的便利

在这里插入图片描述
数组其实就是一个简单哈希表
本题定义一个数组,记录字符串s里字符出现的次数
在这里插入图片描述
时间复杂度为 O ( n ) O(n) O(n),空间上因为定义是的一个常量大小的辅助数组,所以空间复杂度为 O ( 1 ) O(1) O(1)
伪代码:

(1)定义一个辅助数组hash[26],每个元素初始化为0,记录每个字符出现的次数
(2)遍历s字符串,每个字符出现+1
(3)遍历t字符串,每个字符出现-1
(4)遍历hash[26]数组,如果里面有不为0的元素,返回false,否则遍历完返回true

C++:

class Solution {
public:
    bool isAnagram(string s, string t) {
        int hash[26] = {0};
        // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以
        for (int i = 0; i < s.size(); i++)
        {
            hash[s[i] - 'a']++;
        }
        for (int i = 0; i < t.size(); i++)
        {
            hash[t[i] - 'a']--;
        }
        for (int i = 0; i < 26;i++)
        {
            // 数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符
            if (hash[i] != 0) return false;
        }
        // 数组所有元素都为零0,说明字符串s和t是字母异位词
        return true;
    }
};

Python:

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        hash = [0] * 26
        for i in s:
            hash[ord(i) - ord('a')] += 1 # ord()返回ASCII值
        for i in t:
            hash[ord(i) - ord('a')] -= 1
        for i in range(26):
            if hash[i] != 0:
                return False
        return True

3 两个数组的交集

本题考虑什么时候用数组,什么时候用set
在这里插入图片描述
参考博客:C++常用语法——unordered_set
该题目特别说明:输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的, 同时可以不考虑输出结果的顺序
本题考虑用数组或者用set

使用数组来做哈希的题目,是因为题目限制了数值的大小,如果没有限制,就无法使用数组来做哈希表了。如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费

使用unordered_set 读写效率是最高的,并不需要对数据进行排序,本题不让数据重复,所以选择unordered_set
在这里插入图片描述
伪代码:

(1)创建一个存放结果的unordered_set
(2)将nums1转换为unordered_set
(3)遍历nums2,如果发现nums2里的元素在nums_set出现过,将元素插入存放结果的unordered_set
(4)返回result_set

用unordered_set
C++:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set;// 存放结果, 用unordered_set是为了给结果去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (auto i : nums2)
        {
            // 发现nums2的元素 在nums_set里又出现过
            if (nums_set.find(i) != nums_set.end())
            {
                result_set.insert(i);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

时间复杂度: O ( m + n ) O(m+n) O(m+n)
空间复杂度: O ( n ) O(n) O(n)
Python:

class Solution(object):
    def intersection(self, nums1, nums2):
        return list(set(nums1) & set(nums2))

用数组

因为leetcode改了数据,增加了数值范围,所以本题可以用数组。使用数组来做哈希表,因为数组都是 1000以内的

C++:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set;
        int hash[1010] = {0};
        for (auto i : nums1) // nums1中出现的字母在hash数组中做记录
        {
            hash[i] = 1;
        }
        for (auto i : nums2)// nums2中出现话,result记录
        {
            if (hash[i] == 1) result_set.insert(i);
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

时间复杂度: O ( m + n ) O(m+n) O(m+n)
空间复杂度: O ( n ) O(n) O(n)
Python:

class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        count1 = [0] * 1010
        count2 = [0] * 1010
        result = []
        for i in range(len(nums1)):
            count1[nums1[i]] += 1
        for j in range(len(nums2)):
            count2[nums2[j]] += 1
        for k in range(1010):
            if count1[k]*count2[k]>0:
                result.append(k)
        return result

4 快乐数

在这里插入图片描述
思路:
题目中说会无限循环,就是说求和的过程中,sum会重复出现

当遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止

C++:

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

时间复杂度: O ( l o g n ) O(logn) O(logn)
空间复杂度: O ( l o g n ) O(logn) O(logn)
Python:

class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        record = set()
        while True:
            n = self.get_sum(n)
            if n == 1:
                return True
            if n in record:
                return False
            else:
                record.add(n)
    def get_sum(self, n):
        new_sum = 0
        while n:
            n, r = divmod(n, 10)
            new_sum += r ** 2
        return new_sum

5 两数之和

数组,set之后,使用map解决哈希问题
在这里插入图片描述

使用哈希法:当查询一个元素是否出现过,或者一个元素是否在集合里

本题要知道元素有无遍历过,还需要知道元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适

使用数组和set来做哈希法的局限

(1)数组的大小受限制,而且元素少,而哈希值太大会造成内存空间的浪费
(2)set是一个集合,里面放的元素只能是一个key,而这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x,y的下标。所以set也不能用

此时选择另一种数据结构:map

map是一种key value的存储结构,可以用key保存数值,用value再保存数值所在的下标。

在这里插入图片描述
这道题目中并不需要key有序,选择std::unordered_map效率更高
接下来明确两点:
(1)map用来做什么

map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

(2)map中的key和value分别表示什么

给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素
在这里插入图片描述
在这里插入图片描述
伪代码:

unordered_map<int, int> map;
for (i = 0; i < nums.size; i++)
{
	s = target - nums[i];
	iter = map.find(s);
	if (iter != map.end()) return {iter->value, i};
	map.insert(nums[i], i);
}
return {};

C++:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> map; // map存放遍历过的元素
        // 遍历当前元素,并在map中寻找是否有匹配的key
        for (int i = 0; i < nums.size(); i++)
        {
        	int s = target - nums[i];
        	auto iter = map.find(s);
        	if (iter != map.end()) return { iter->second, i};
        	// 如果没找到匹配对,就把访问过的元素和下标加入到map中
        	map.insert(pair<int, int>(nums[i], i));
        }
        return {};
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

Python:

records = dict()
        # 遍历当前元素,并在map中寻找是否有匹配的key
        for index, value in enumerate(nums):
            if target - value in records:
                return [records[target - value], index]
            records[value] = index # 如果没找到匹配对,就把访问过的元素和下标加入到map
        return []

本题有四个要点:
(1)为什么会想到用哈希表
查询元素有没有再出现,元素在不在这个集合里
(2)哈希表为什么用map
因为用数组和集合有局限,数组的大小受限制,而且元素少,而哈希值太大会造成内存空间的浪费。集合是里面放的元素只能是一个key,本题还要返回对应元素的下标
(3)本题map是用来存什么的
map是用来存放遍历过的元素
(4)map中的key和value用来存什么的
key用来存放元素,value用来存放元素对应的下标


鼓励坚持六天的自己😀😀😀

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

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

相关文章

Rust 枚举和模式匹配

目录 1、枚举的定义 1.1 Option 枚举和其相对于空值的优势 2、match 控制流结构 2.1 匹配 Option 2.2 匹配是穷尽的 2.3 通配模式和 _ 占位符 3、if let 简洁控制流 1、枚举的定义 枚举&#xff08;enumerations&#xff09;&#xff0c;也被称作 enums。枚举允许你通过…

微信小程序 纯css画仪表盘

刚看到设计稿的时候第一时间想到的就是用canvas来做这个仪表盘&#xff0c;虽然本人的画布用的不是很好但还可以写一写&#x1f600;。话不多说直接上代码。最后有纯css方法 <!--wxml--> <canvas canvas-id"circle" class"circle" >// js dat…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《考虑富氧燃烧技术的电–气–热综合能源系统低碳经济调度》

这个标题涉及到一个关于能源系统和经济调度的复杂主题。让我们逐步解读&#xff1a; 电–气–热综合能源系统&#xff1a; 指的是一个综合的能源系统&#xff0c;包括了电力、气体&#xff08;可能是天然气等&#xff09;、热能等多个能源形式。这种系统的设计和优化旨在使不同…

【数据结构(六)】排序算法介绍和算法的复杂度计算(1)

文章目录 1. 排序算法的介绍1.1. 排序的分类 2. 算法的时间复杂度2.1. 度量一个程序(算法)执行时间的两种方法2.2. 时间频度2.2.1. 忽略常数项2.2.2. 忽略低次项2.2.2. 忽略系数 2.3. 时间复杂度2.4. 常见的时间复杂度2.5. 平均时间复杂度和最坏时间复杂度 3. 算法的空间复杂度…

编码器-解码器(seq-seq)

1. 背景 encoder-decoder和seq-seq模型可以解决输入与输出都是不定长序列的问题。它们都用到了两个循环NN&#xff0c;分别叫做编码器(用来分析输入序列)与解码器(用来生成输出序列)。 2. 编码器 把一个不定长的输入序列变换成一个定长的背景变量c&#xff0c;并在其中编码输入…

分享72个节日PPT,总有一款适合您

分享72个节日PPT&#xff0c;总有一款适合您 72个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/17Lmlvd_xN-xRSKu3FZUS9w?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

驱动开发--内核添加新功能

Ubuntu下这个文件为开发板ls命令的结果 内核的内容&#xff1a; mm&#xff1a;内存管理 fs&#xff1a;文件系统 net&#xff1a;网络协议栈 drivers&#xff1a;驱动设备 arch与init&#xff1a;跟启动相关 kernel与ipc&#xff1a;任务&#xff0c;进程相关 向内核增…

java项目日常运维需要的文档资料

一、前言 java项目开发完成&#xff0c;部署上线&#xff0c;进入项目运维阶段&#xff0c;日常工作需要准备哪些资料和文档?当项目上线后&#xff0c;运行一段时间&#xff0c;或多或少会遇到一些运维上的问题&#xff0c;比如服务器磁盘饱满&#xff0c;服务器CPU&#xff0…

分享 | 顶刊高质量论文插图配色(含RGB值及16进制HEX码)(第一期)

我在很早之前出过一期高质量论文绘图配色&#xff0c;但当时觉得搜集太麻烦于是就没继续做&#xff0c;后来用MATLAB爬了上万张顶刊绘图&#xff0c;于是又想起来做这么一个系列&#xff0c;拿了一个多小时写了个提取论文图片颜色并得出RGB值和16进制码并标注在原图的代码&…

GPTs每日推荐--生化危机【典藏版】

今天给大家推荐一个游戏性质的GPTs&#xff0c;叫做生化危机典藏版&#xff0c;国内点击可玩。 开篇&#xff1a;玩家从末日中醒来。 选择&#xff1a;玩家会遇到各种资源、任务、剧情&#xff0c;需要自行选择相关的分支剧情&#xff0c;一旦选错&#xff0c;无法重选。 结局…

一次北斗接收机调试总结

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 最近项目中要用到北斗接收机&#xff0c;它的样子是长这样的&#xff1a; 这部机器里面是没有操作系统的&#xff0c;由单片机控制。最近我们要根据协议…

Linux socket编程(10):UDP详解、聊天室实现及进阶知识

首先来回顾以下TCP的知识&#xff0c;TCP是一种面向连接的、可靠的传输协议&#xff0c;具有以下特点&#xff1a; TCP通过三次握手建立连接&#xff0c;确保通信的可靠性和完整性使用流控制和拥塞控制机制&#xff0c;有效地调整数据传输的速率&#xff0c;防止网络拥塞TCP提…

使用 PyTorch 进行 K 折交叉验证

一、说明 中号机器学习模型在训练后必须使用测试集进行评估。我们这样做是为了确保模型不会过度拟合&#xff0c;并确保它们适用于现实生活中的数据集&#xff0c;与训练集相比&#xff0c;现实数据集的分布可能略有偏差。 但为了使您的模型真正稳健&#xff0c;仅仅通过训练/测…

OneNote for Windows10 彻底删除笔记本

找了超多方法&#xff0c;都没有用&#xff0c;我的OneNote都没有文件选项&#xff0c;要在OneDrive中删除&#xff0c;但是一直登不进&#xff0c;然后又找到一个方法&#xff1a; 在网页中打开Office的控制面板 "Sign in to your Microsoft account" 在“最近”一…

k8s volumes and data

Overview 传统上&#xff0c;容器引擎(Container Engine)不提供比容器寿命更长的存储。由于容器被认为是瞬态(transient)的&#xff0c;这可能会导致数据丢失或复杂的外部存储选项。Kubernetes卷共享 Pod 生命周期&#xff0c;而不是其中的容器。如果容器终止&#xff0c;数据…

ctfhub技能树_web_信息泄露

目录 二、信息泄露 2.1、目录遍历 2.2、Phpinfo 2.3、备份文件下载 2.3.1、网站源码 2.3.2、bak文件 2.3.3、vim缓存 2.3.4、.DS_Store 2.4、Git泄露 2.4.1、log 2.4.2、stash 2.4.3、index 2.5、SVN泄露 2.6、HG泄露 二、信息泄露 2.1、目录遍历 注&#xff1…

POI Excel导入导出(下)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 上一篇通过四个简单的小…

力扣刷题day1(两数相加,回文数,罗马数转整数)

题目1&#xff1a;1.两数之和 思路1和解析&#xff1a; //1.暴力枚举解法(历遍两次数组&#xff0c;时间复杂度O&#xff08;N^2)&#xff0c;空间复杂度O&#xff08;1&#xff09; int* twoSum(int* nums, int numsSize, int target, int* returnSize) {for (int i 0; i &…

短波红外相机的原理及应用场景

短波红外 (简称SWIR&#xff0c;通常指0.9~1.7μm波长的光线) 是一种比可见光波长更长的光。这些光不能通过“肉眼”看到&#xff0c;也不能用“普通相机”检测到。由于被检测物体的材料特性&#xff0c;一些在可见光下无法看到的特性&#xff0c;却能在近红外光下呈现出来&…

使用Python Flask搭建Web问答应用程序并发布到公网远程访问

使用Python Flask搭建web问答应用程序框架&#xff0c;并发布到公网上访问 文章目录 使用Python Flask搭建web问答应用程序框架&#xff0c;并发布到公网上访问前言1. 安装部署Flask并制作SayHello问答界面2. 安装Cpolar内网穿透3. 配置Flask的问答界面公网访问地址4. 公网远程…