首页 > 其他分享 >代码随想录打卡 Day 3

代码随想录打卡 Day 3

时间:2025-01-01 17:40:30浏览次数:1  
标签:std map set 元素 随想录 unordered 哈希 打卡 Day

代码随想录打卡 Day 3

1. 哈希表的理论基础

哈希表的定义

哈希表是根据关键码的值直接访问数据的数据结构,一般用来快速判断一个元素出现在集合中。

数组就可以看成是一张哈希表,这张哈希表中的关键字 就是数组的索引下标,值就是数组中的元素。

哈希表的基本概念

哈希表的基本概念包括:

  • 哈希函数:对于关键字$k$,通过哈希函数将其储存到$f(k)$的位置,因此,不需要通过比较就可以获取所查的记录。
  • 哈希碰撞:对于不同的关键字,可能得到同一个散列地址,这一现象为哈希碰撞。一般来说,哈希碰撞的解决方法有拉链法线性探测法,在此不再赘述。

哈希表的常见结构:

使用哈希表解决问题时,常见的数据结构有:数组set(集合),map(映射)

在CPP中,set在STL中共有三种实现方式,如下表所示:

集合 底层实现 是否有序 值是否重复 能否更改值 查询效率 增删效率
std::set 红黑树 有序 $O(log n)$ $O(logn)$
std::multiset 红黑树 有序 $O(log n)$ $O(logn)$
std::unordered_set 哈希表 无序 $O(1)$ $O(1)$

map的底层实现同样包括三种:

映射 底层实现 是否有序 key是否重复 能否更改key 查询效率 增删效率
std::map 红黑树 有序 $O(log n)$ $O(logn)$
std::multimap 红黑树 有序 $O(log n)$ $O(logn)$
std::unordered_map 哈希表 无序 $O(1)$ $O(1)$

使用哈希法时,不同的数据结构一般有不同的使用场景,如下所示:

数据结构 适用场景
数组 当键的范围是有限且连续的整数时
集合 只需要存储唯一值,并且只关心元素是否存在而不关心它们的数量或关联值时
映射 需要将键映射到值上,并且可能需要根据键快速查找对应的值

2.有效的字母异位词

leetcode题号:242.有效的字母异位词

【题目描述】

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1: 输入: s = "anagram", t = "nagaram" 输出: true

示例 2: 输入: s = "rat", t = "car" 输出: false

说明: 你可以假设字符串只包含小写字母。

【题目分析】

在本题中,我们可以定义一个长度为26的数组record初始化为0。这是因为字符az的ASCII值为26个连续数值。

在遍历字符串s时,只需要对s[i]-'a'所在元素+1即可,并不需要记住ASCII码,只需要求出一个相对数值即可。

检查字符串t是否出现了这些字符?在遍历字符串t的过程中,对t出现的字符映射到索引上的值-1即可。

如果record数组中的元素不全为0,则说明s与t不是有效的字符异位词,返回false。

本题的相关代码如下:

bool isAnagram(string s, string t) {
    int record[26]={0};//新建一个数组,用来记录每个字母出现的次数
    for(int i=0;i<s.size();i++){ //对string s 遍历
        record[s[i]-'a']++;  //s[i]-'a'是计算s[i]在字母表中的位置,然后record[s[i]-'a']++,即记录每个字母出现的次数
    }


    for(int i=0;i<t.size();i++){ //对string t 遍历
        record[t[i]-'a']--;
    }

    for (int i=0;i<26;i++){
        if(record[i]!=0){
            return false;
        }
    }

    return true;//record所有数组元素均为0
}

相比于暴力解法,该解的时间复杂度为$O(n)$,空间复杂度为$O(n)$.

3. 两个数组的交集

leetcode题号:349.两个数组的交集

【题目描述】

计算两个数组的交集,交集中的元素是唯一的。

【题目分析】

解答本题,主要是学习哈希数据结构—unordered_set.

题目中睡哦名,输出的每一个元素一定是唯一的,同时不需要考虑输出结果的顺序。

如上一题所讲,将数组当作哈希表页数不错的选择,但本题中,数组元素内容并没有限制。如果哈希值较少,比较分散,跨度大,使用数组作为哈希表数据结构就会造成很大的内存空间浪费。此时,就应该适用set这种数据结构。

第一部分的表格已经指出了三种set数据结构的差异。其中std::unordered_set的底层实现是哈希表,不同于其他两种结构依赖红黑树。适用unordered_set的I/O效率是最高的,不需要对数据进行排序的同时保证了数据的唯一性。

unordered_set的基本操作

unordered_set的基本操作如下:

# 构造函数
std::unordered_set<int> uset;

# 插入元素
uset.insert(10);

# 查找元素
auto it = uset.find(10);
#如果查找失败,it == uset.end();

# 遍历元素
for(auto it = uset.begin(),it != uset.end(); it++){
    \*  for loop *\
}
# 其中begin()方法提供一个正向迭代器,end()方法提供一个福祥迭代器

# 删除元素
uset.erase(10);

# 大小与空检查
size_t size = uset.size();
bool isEmpty = uset.empty();

# 清空容器
uset.clear();

# 返回unordered_set中所有元素
return vector<int>(uset.begin(),uset.end())
  • unorder_set.find()为什么需要与unorder_set.end()进行判断?

find() 方法总是返回一个迭代器,但这个迭代器可能指向实际存在的元素,也可能指向容器的结尾(end())。因此,在使用 find() 的结果之前,必须先检查返回的迭代器是否有效(即不是 end()),以避免非法访问或未定义行为。这样的判断是必要的,因为它帮助开发者安全地处理不存在的情况,防止程序崩溃或者产生意外的结果.

本题的实现代码如下:

vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    unordered_set<int> res;		//存放结果
    unordered_set<int> s1(nums1.begin(),nums1.end());
    for (auto i : nums2) { //对nums2中元素进行迭代
        if (s1.find(i) != s1.end()) { //发现nums2中的元素在s1中出现过
            res.insert(i);
        }
    }
    return vector<int>(res.begin(),res.end());
}

4.两数之和

leetcode题号:1.两数之和

【题目描述】

在数组中找到两个元素的数值之和为目标值,返回这两个元素的下标

【题目分析】

很显然,直观的想法是使用暴力解,两层for循环寻找元素

如果使用哈希法,本题可以使用map。CPP中map有三种类型,而本题不需要有序输出,因此可以使用unordered_map即可。

unordered_map的基本操作

// 默认构造
std::unordered_map<int, std::string> myMap;

// 构造并初始化
std::unordered_map<int, std::string> myMap = {{1, "one"}, {2, "two"}};

// 构造并指定初始容量
std::unordered_map<int, std::string> myMap(10);

// 构造并复制另一个 unordered_map
std::unordered_map<int, std::string> anotherMap = myMap;

# 插入元素
MyMap.insert({3."three"});
MyMap.insert(pair<int,int>(nums[i],i));

# 删除元素
myMap.erase(1);

# 查找元素
auto it = myMap.find(2); // 查找键为2的元素
if (it != myMap.end()) {
    std::cout << "Found: " << it->second << std::endl;
}

# map中first。second属性
key=iter -> first;
value=iter -> second;

本题的代码实现如下:

vector<int>  twoSum(vector<int>& nums, int target) {
    std::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};
            }
             map.insert(pair<int, int>(nums[i], i));
        }
   return {};

}

通过Map操作,时间复杂度降为$O(n)$,空间复杂度为$O(n)$.

标签:std,map,set,元素,随想录,unordered,哈希,打卡,Day
From: https://www.cnblogs.com/kotoriinsky/p/18646115

相关文章

  • 工学云智能打卡,异地签到
    在当今快节奏的学习和工作环境中,如何高效管理时间和优化流程成为许多职场人士和学生共同面临的挑战。为此,我们团队开发了一款专为工学云app设计的云打卡系统,该系统通过智能定位技术和GPT4技术的应用,旨在彻底改变传统打卡和报告撰写的方式,为用户提供更便捷、高效的学习与工作体......
  • 代码随想录打卡 Day 2
    代码随想录打卡Day21.链表的定义与操作链表作为基本的数据结构类型,其主要形式有三种:单链表双链表循环链表由于刷代码题平时在OJ上默认定义已经给出,可以直接使用。而在面试/机试时,一般需要需要自己手写链表。因此,正确写出链表的定义是非常有必要的。一个单链表的......
  • 【Java教程】Day15-16 多线程:线程同步——Java的原子操作类
    在Java中,除了常见的底层锁和并发集合类,java.util.concurrent 包还提供了一组专门用于原子操作的封装类,位于 java.util.concurrent.atomic 包。通过这些类,我们可以在多线程环境下安全地进行无锁操作,避免了传统锁的性能开销。今天我们就来详细了解其中一个常用的类:AtomicInt......
  • 【Java教程】Day14-01 加密与安全:从ASCII到Base64
    ​1.什么是编码?在计算机科学中,编码(Encoding)是将信息从一种格式转换成另一种格式的过程。在我们日常生活中,编码算法广泛应用于文本、文件和网络传输等领域。了解编码的基础知识是学习计算机编程与算法的第一步。1.1ASCII编码ASCII(AmericanStandardCodeforInformationI......
  • 【Java教程】Day11-07 时间与日期:日期与时间API的转换与数据库存储
    Java提供了两个日期与时间处理API:旧的 java.util.Date 和 java.util.Calendar,以及新的 java.time 包。新的API以 Instant、LocalDateTime 等为核心,具有更清晰的设计和更强大的功能。除非你需要与遗留代码进行交互,否则建议使用新的API。在需要将新旧API进行转换时,......
  • 打卡信奥刷题(523)用C++信奥P6861[普及组/提高] [RC-03] 难题
    [RC-03]难题题目描述求两个整数a,ba,ba,b(......
  • Linux第一课:c语言 学习记录day01
    0、大纲1、Linux命令2、基础内容:进制转换、词法符号、变量常量、输入输出3、语句:分支语句、循环语句、循环控制语句4、数组:一维数组、字符数组、排序、二维数组5、指针:一级指针、二级指针、指针和数组、指针数组、数组指针6、函数:函数基本用法、string函数族、开辟堆区空......
  • 八股day1——HashMap
    HashMap回答重点数组+链表+红黑树超过负载因子会*2扩容,扩容操作比较耗时尾插法,头插法在多线程中可能会形成回路,可以参考BV1n541177Ea红黑树优化当链表长度超过8时,链表会转变为红黑树,查找复杂度从O(n)降到O(logn),如果树中元素低于6,则转换回链表,减少不表的树操作开销hashC......
  • Day1算法刷题(数组板块)
    二分查找注意事项left<=right,等于不能漏掉,定位到同一个元素的时候也要判断和target是否相等left=mid+1,right=mid-1而不能是mid,否则会死循环,比如nums={1,2},target=2,此时mid就会一直指向1。补充:数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分......
  • [CEOI2010 day2] pin
    思路看到「恰好」触发被动了考虑套路转化,令\(f(k)\)表示「至少」有\(k\)个对应位置的字符不同的字符串对数套路的,令\(g(k)\)表示「恰好」有\(k\)个对应位置的字符不同的字符串对数\[f(k)=\sum_{i=k}^{n}{n\choosei}g(i)\iffg(k)=\sum_{i=k}^{n}(-1......