代码随想录刷题题Day5

刷题的第五天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀
刷题语言: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用来存放元素对应的下标


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

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

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

相关文章

Db2的Activity event monitor在Db2 MPP V2上收集ROWS_INSERTED信息

注&#xff1a;本文不是讲解Db2 Activity event monitor&#xff0c;只是一个用法实践。要了解Activity event monitor&#xff0c;请参考 https://www.ibm.com/docs/en/db2/11.5?topicevents-activity-event-monitoring 。 环境 Red Hat Enterprise Linux release 8.8 (Oot…

“构建智慧城市,共享美好生活“2024杭州国际智慧城市展览会

智慧城市作为当今社会发展的必然趋势&#xff0c;正在被越来越多的企业和观众所关注。为了进一步推动智慧城市的发展&#xff0c;2024杭州智慧城市展览会将于4月份在杭州国际博览中心盛大召开。目前&#xff0c;招商工作已近半程&#xff0c;大批国内外知名企业踊跃报名&#x…

会话技术(Cookie与Session)

会话技术 一.作用域对象 1.作用域对象概述 有作用域的对象作用域对象可以用来存储数据并且可以在不同的组件之间进行传递传递的范围受作用域的限制&#xff0c;一旦超过范围&#xff0c;立即失效 2.两个作用域对象 作用域对象描述request对象作用范围是一次请求ServletCon…

3D Gaussian Splatting的使用

3D Gaussian Splatting的使用 1 下载与安装2 准备场景样本2.1 准备场景照片2.1.1 采集图片2.1.2 生成相机位姿 3 训练4 展示 1 下载与安装 今年SIGGRAPH最佳论文&#xff0c;学习了一下&#xff0c;果然厉害&#xff0c;具体论文原理就不说了&#xff0c;一搜都有&#xff0c;…

HOST文件被挟持,无法上网,如何解决。

问题&#xff1a; 晚上开机&#xff0c;突然发现无法联网&#xff0c;提示网络异常 解决&#xff1a; 首先网络诊断&#xff0c;host文件被劫持&#xff0c;修复后&#xff0c;仍然不行。 然后测试手机热点&#xff0c;发现仍然无法联网 尝试用火绒修复&#xff0c;无果。 所有…

安路Anlogic FPGA下载器的驱动安装教程

安路FPGA下载器驱动安装教程 安路FPGA下载器&#xff1a;EN-ALC10,是一款高性能FPGA下载线&#xff08;编程器&#xff09;&#xff0c;支持安路的开发软件TDS和全系列FPGA芯片下载编程&#xff0c;支持全速USB2.0与电脑进行数据通信&#xff0c;通过JTAG协议与FPGA进行程序下…

【mysql】基于binlog数据恢复指令和坑

文章目录 1.binlog相关配置是否开启binlogbinlog日志格式 2.导出binlog日志mysqlbinlog指令updateinsertdeletebinlog中的事件 3.数据恢复4.特别注意的坑为什么bash脚本执行mysqlbinlog&#xff0c;无法找到指令为什么执行mysqlbinlog&#xff0c;无法数据恢复 1.binlog相关配置…

【杂】解决关于mean(0)理解错误引发的程序bug

一、环境和解释器要一起配置好 invalid syntax 发生你在终端激活了一个环境&#xff0c;但 VSCode 依然使用之前的解释器的情况。 解释器设置影响了 VSCode 中运行 Python 脚本、调试、代码补全等功能的行为。VSCode 会根据你选择的解释器来执行这些操作。 二、关于mean&#x…

【c】序列中整数去重

数组中的元素不好直接删除&#xff0c;我们可以把重复的数做标记&#xff0c;将他赋值为0&#xff0c;然后正常打印数组&#xff0c;为0的跳过 #include<stdio.h> int main() {int n;scanf("%d",&n);int arr[n1];for(int i1;i<n;i){scanf("%d&quo…

fastadmin列表头部按钮批量上传视频

上传界面通过layui生成 index.html <a href="{:url(video/piliangadd)}" class="btn btn-success btn-piliangadd btn-dialog {:$auth->check(video/piliangadd)?:hide}" title="批量上传" ><i class="fa fa-plus">…

【力扣热题100】207. 课程表 python 拓扑排序

【力扣热题100】207. 课程表 python 拓扑排序 写在最前面207. 课程表解决方案&#xff1a;判断是否可以完成所有课程的学习方法&#xff1a;拓扑排序实现步骤Python 实现性能分析结论 写在最前面 刷一道力扣热题100吧 难度中等 https://leetcode.cn/problems/course-schedule…

关于如何解决问题?代码习惯。

警钟长鸣 从师哥身上学到的东西&#xff1a; 关于如何解决问题&#xff1f; 1、沟通&#xff1a;有效的沟通&#xff0c;将问题描述清楚&#xff0c;让老师和师哥明白你出了什么问题&#xff0c;给出建议&#xff0c;很多时候一句良言胜过自己摸索很久 2、出现问题由浅入深地…

AI 大模型时代的计算机网络通信

下午跟朋友聊天&#xff0c;聊到编码和传输&#xff0c;兴致未尽&#xff0c;有必要继续说说有损传输&#xff0c;承接 从意义中恢复而不从数据包恢复。 在 AI 大模型催化下&#xff0c;网络通信方式将完全不同&#xff0c;依赖编码的柔性&#xff0c;有损传输将比 tcp/ip 更具…

android studio 打开flutter项目 出现 dart sdk is not configured

android studio 版本 flutter版本 解决方式 1 点击Open Dart setting 2 打勾Enable Dart support for the project 3 Dart SDK path 选择flutter/bin/cache/dart-sdk 4 打勾Enable Dart support for the following modules

JVM Optimization Learning(五)

一、JVM Optimization 1、G1 G1官网说明&#xff1a;Garbage First Garbage Collector Tuning The Garbage First Garbage Collector (G1 GC) is the low-pause, server-style generational garbage collector for Java HotSpot VM. The G1 GC uses concurrent and paralle…

电子学会C/C++编程等级考试2022年09月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:最长上升子序列 一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序列(ai1, ai2, …, aiK),这里1 <= i1 < i2 < … &l…

Android中的动态代理详解

在说动态代理之前&#xff0c;先来简单看下代理模式。代理是最基本的设计模式之一。它能够插入一个用来替代“实际”对象的“代理”对象&#xff0c;来提供额外的或不同的操作。这些操作通常涉及与“实际”对象的通信&#xff0c;因此“代理”对象通常充当着中间人的角色。 代…

WPF halcon 机器视觉

1 鼹鼠的故事第14集 鼹鼠与智能房 鼹鼠无意中坐进了一辆小汽车&#xff0c;小汽车开进了一所智能住宅。鼹鼠看到房主在智能房里&#xff0c;享受着现代化的服务。趁着主人看电视的时候&#xff0c;鼹鼠也享用了一顿丰盛的智能晚餐。 小编大胆的畅想&#xff0c;这些食物 前一秒…

论文解读--PointPillars- Fast Encoders for Object Detection from Point Clouds

PointPillars--点云目标检测的快速编码器 摘要 点云中的物体检测是许多机器人应用(如自动驾驶)的重要方面。在本文中&#xff0c;我们考虑将点云编码为适合下游检测流程的格式的问题。最近的文献提出了两种编码器;固定编码器往往很快&#xff0c;但牺牲了准确性&#xff0c;而…

初识计算机网络

网络通信基础 1. IP地址2.端口号3.认识协议3.1协议分层 4. 网络数据传输的基本流程4.1 五元组4.2封装和分用 1. IP地址 IP地址主要用于表示网络主机,其他网络设备的网络地址,IP地址用于定位主机的网络地址 比如:发送快递的时候,需要知道对象的收货地址,才能将包裹送到目的地. …