leetcode-哈希表

1. 理论

从哈希表的概念、哈希碰撞、哈希表的三种实现方式进行学习

在这里插入图片描述

哈希表:用来快速判断一个元素是否出现集合里。也就是查值就能快速判断,O(1)复杂度;

哈希碰撞:拉链法,线性探测法等。只是一种思想,刷题我们自己是无需实现的,只是使用;

哈希表的三种实现方式:数组,set(集合),map(映射)。其中集合和映射分别又有三种实现。

2. 做题的时候用到的小tip:

  1. set和vector不能直接相互转换,但可以通过遍历一个容器并将其元素插入另一个容器实现数据转换。

以下是将 std::set 转换为 std::vector 和将 std::vector 转换为 std::set 的示例:

std::set 转换为 std::vectorstd::vector<int> myVector(mySet.begin(), mySet.end());

std::vector 转换为 std::setstd::set<int> mySet(myVector.begin(), myVector.end());

如果不是定义,直接return的时候,就用return set<int>(myVector.begin(), myVector.end()); 就行。

3. 有效的字母异位词

本题用数组就能完成,但是用到的是哈希思想。

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.length()!=t.length())
            return false;
        int hash[26] = {0};
        for(char i : s){
            hash[i-'a']++;
        }
        for(char i : t){
            hash[i-'a']--;
        }
        for(int i : hash){
            if(i != 0)  return false; 
        }
        return true;
    }
};

4. 两个数组的交集Leetcode349. 20230904 set操作、转换、哈希思想

如果使用unordered_set(底层为哈希表),代码如下:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int>result_nums;// 最终返回的交集
        unordered_set<int>tmp_nums(nums1.begin(), nums1.end());// 用于比较的集合        
        for(int i : nums2){
            if(tmp_nums.find(i) != tmp_nums.end()){
                result_nums.insert(i);
            }
        }
        return vector<int>(result_nums.begin(),result_nums.end()); 

    }
};

写这一题的时候由于不熟悉set和vector之间的相互转换,卡了好久。思路倒是不难,但是要声明两个unordered_set。先是用第一个uset存nums1的所有值,然后比较nums2是否在uset里,如果在,就加入到第二个uset中去。

所以为什么要用一个uset存,而不是直接用nums2与vector的nums1比呢?这就是本题的哈希所在,因为对于unordered_set查找只需O(1时间,如果直接将nums2nums1vector比较,那么每次查找操作的平均时间复杂度将是O(n),因为在vector中查找元素需要遍历整个vector,而不是像unordered_set一样具有O(1)的查找时间。这会导致整个算法的时间复杂度更高。

这种做法的主要优势在于查找的时间复杂度更低,使得整个算法的性能更好。

如果使用数组,也是类似的:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result;
        int tmp[1000]={0};
        for (int i : nums1){
            tmp[i] = 1;
        }
        for (int j : nums2){
            if(tmp[j] == 1)
                result.insert(j);
        }
    
        return vector<int>(result.begin(),result.end());
    }
};

先用tmp 01数组存nums1中出现过的值,然后遍历nums2看tmp数组对应有没有变过,变过则插入uset。

然后我又做了一个不去重的交集题,麻烦的是有个限制条件让我们次数不一致取最小值,就要使用find之后erase iterator而不能直接用erase。这个也是我上网查了之后才知道的。

class Solution {

public:

    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {

        // 不去重,考虑使用multiset

        multiset<int> result;

        multiset<int> tmp(nums1.begin(),nums1.end());

        for(int i : nums2){

            auto it = tmp.find(i);

            if(it != tmp.end()){

                result.insert(i);

                tmp.erase(it);

            }

        }

        return vector<int>(result.begin(),result.end());

    }

};

这个我没检查就提交一次过了,晕晕

5. 快乐数 LeetCode. 202 20230905

这一题居然不是数学是哈希 还真是没想到。并且,这一题对于各位数取平方再相加的操作是我要学习的,当时写的时候觉得很头大,没想到包装成一个函数之后还是很容易的。

class Solution {
public:
    int calculatesum(int n){
        int sum = 0;
        while (n){
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        // 计算平方,填入哈希表并比较
        unordered_set<int> myset;
        int sum = n;
        while(sum != 1){
            sum = calculatesum(sum);
            if(myset.find(sum) != myset.end()){
                return false;
            }   
            else{
                myset.insert(sum);
            } 
        }
        return true;
        
    }
};

6.两数之和 LeetCode 1. 20230905

老生常谈的题,但是每次做都有不一样的感受。前年只会暴力解,去年仅知道可以用unordered_map,今年的进步在于读懂了题目为什么这样出,限制不重复就是为了我们用unorder_map,限制时间复杂度其实就是提示unordered的查询和插入效率均为O(1)。

还有一个就是

iter->second     ,不带括号  

和return {a,b}; 这个用法不能忘掉。开始写的小括号,又换成中括号。

还有pair操作,是insert((pair)<int,int>(a,b))

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

思想是遍历vector,用unordered_map存放之前遍历过的元素集合和它们对应的序号,每遍历到一个元素,在遍历过的集合里找是否有target减它的元素。

7.四数相加 II LeetCode 454. 20230908

思想是两个数组一起。前两个数组用于填充,后两个数组用于查询,跟之前一样。

需要注意的是可以可以直接使用umap[i]++这种操作。

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map<int,int> umap;
        int count = 0;
        for(int i : nums1){
            for(int j : nums2){
                umap[i+j]++;
            }
        }

        for(int i : nums3){
            for(int j : nums4){
                auto it = umap.find(-i-j);
                if(it != umap.end()){
                    count += it->second;
                }
            }
        }
        return count;
    }
};

如果本题想难度升级:就是给出一个数组(而不是四个数组),在这里找出四个元素相加等于0,答案中不可以包含重复的四元组。

8.赎金信 LeetCode383. 20230908

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int character[26]={0};
        for(char i : magazine){
            character[i-'a']++;
        }

        for(char i : ransomNote){
            character[i-'a']--;
            if(character[i-'a'] < 0)
                return 0;
        }

        return 1;
    }
};

现在看到简单题基本就是嘎嘎乱杀了,这一题完全无难度,三分钟秒掉。

有一点需要注意:数组需要初始化……TAT

9. 三数之和

这一题的数据就是一个数组,我还以为跟之前一样,是三个数组。

这一题不建议用哈希法,因为是“去重”的,建议的方法是排序+双指针+去重。

去重是三个地方,我写的代码还跟随想录不一样,先以自己的为主。

遇到了一个坑:i++和continue,应该写continue,因为-4,-2,-2,-2,0,1,2,2,2,3,3,4,4,6,6

这个里面,i如果到了第二个-2,会直接+1,然后到了第三个-2又能够顺利往下运行,然后又会找到和第二个-2相同的三元组。想了好久的。

正确的做法应该是第二个-2:跳过!

第三个-2:跳过!

这样就能到0。

贴一个我自己写出来的代码:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());
        for(int i = 0; i < nums.size(); ++i){
            if(nums[i] > 0)
                return result;
            if(i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            for(int left = i + 1, right = nums.size() - 1; left < right; ){
                if(nums[left] + nums[right] + nums[i] > 0){
                    right--; 
                }
                else if(nums[left] + nums[right] + nums[i] < 0){
                    left++;
                }
                else {
                    result.push_back({nums[i], nums[left], nums[right]}); //找到了一个答案
                    left++;
                    right--;
                    while(left < right && nums[left] == nums[left - 1]) left++;//去重
                    while(left < right && nums[right] == nums[right + 1]) right--;//去重

                }
      
            }
        }
        return result;
    }
};

10.四数之和

在这里插入图片描述

第一次提交通过了239/293个用例。但是,就这一行写了两个bug

①一开始写的不是j>1,复制了i>0过来,写的是if(i>0&&nums[j]==nums[j-1]),通过239/293

在这里插入图片描述
在这里插入图片描述

②后来写成图上的if(j>1&&nums[j]==nums[j-1])完全没考虑i==j的情况,于是改成if(j>i+1&&nums[j]==nums[j-1]),结果通过284/293……服了,然后改成longlong,结果因为中间结果是用int存的,还是不行

在这里插入图片描述

③然后把代码改成了这个丑陋的样子,终于过了,用时一个小时,啥也不想说了

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

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

相关文章

【年终特惠】基于最新导则下生态环评报告编制技术暨报告篇、制图篇、指数篇、综合应用篇系统性实践技能提升

根据生态环评内容庞杂、综合性强的特点&#xff0c;依据生态环评最新导则&#xff0c;将内容分为4大篇章(报告篇、制图篇、指数篇、综合篇)、10大专题(生态环评报告编制、土地利用图的制作、植被类型及植被覆盖度图的制作、物种适宜生境分布图的制作、生物多样性测定、生物量及…

高压放大器在电火花加工中的作用是什么

高压放大器在电火花加工中扮演着至关重要的角色。下面安泰电子将详细介绍高压放大器在电火花加工中的作用。 电火花加工是一种精密加工技术&#xff0c;广泛应用于制造业的模具制造、航空航天、汽车零部件等领域。它通过在工件表面产生高频电火花放电的方式&#xff0c;实现对材…

uniapp实现路线规划

UniApp是一个基于Vue.js框架开发的跨平台应用开发框架&#xff0c;可以同时构建iOS、Android、H5等多个平台的应用。它使用了基于前端技术栈的Web开发方式&#xff0c;通过编写一套代码&#xff0c;即可在不同平台上运行和发布应用。 UniApp具有以下特点&#xff1a; 跨平台开…

Unity内打开网页的两种方式(自带浏览器、内嵌浏览器)

1.自带浏览器 这个比较简单&#xff0c;直接调用unity官方的API即可&#xff0c;会直接使用默认浏览器打开网页&#xff0c;这里就不多做解释了。 代码 public InputField input;private void OpenUrlByUnity(){string inputStr input.text;if (!string.IsNullOrEmpty(input…

单链表练习

单链表练习 相关内容&#xff1a; 1.再理解&#xff1a;LNode、*LinkList 2.单链表的整表创建&#xff08;头插法和尾插法&#xff09; 3.单链表的读取、插入、删除 4.单链表的整表删除 //单链表的初始化、创建、插入、删除、查找 //结点的结构体&#xff1a;数据域、指针域 …

开放式耳机能保护听力吗,开放式耳机跟骨传导耳机哪个更好?

如果从严格意义上来讲的话&#xff0c;开放式耳机中的骨传导耳机是能保护听力&#xff0c;现如今的开放式耳机是一个统称&#xff0c;将所有不入耳的类目全部规划到一块。因此在开放式耳机中存在着一些耳机是只能够保持周边环境音&#xff0c;而不是保护听力的。 下面让我来给…

linux下的程序环境和预处理(gcc演示)

1. 程序的翻译环境和执行环境 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 第2种是执行环境&#xff0c;它用于实际执行代码。 2. 详解编译链接 2.1 翻译环境 组成一个程序的…

MySQL连接的原理⭐️4种优化连接的手段性能提升240%

MySQL连接的原理⭐️4种优化连接的手段性能提升240%&#x1f680; 前言 上两篇文章我们说到MySQL优化回表的三种方式&#xff1a;索引条件下推ICP、多范围读取MRR与覆盖索引 MySQL的优化利器⭐️索引条件下推&#xff0c;千万数据下性能提升273%&#x1f680; MySQL的优化…

函数式接口详解(Java)

函数式接口详解&#xff08;Java&#xff09;_函数式接口作为参数_凯凯凯凯.的博客-CSDN博客 函数式接口&#xff1a;有且仅有一个抽象方法的接口 Java中函数式编程体现就是Lambda表达式&#xff0c;所以函数式接口就是可以适用于Lambda使用的接口 只有确保接口中仅有一个抽…

【设计模式】第7节:创建型模式之“建造者模式”

Builder模式&#xff0c;中文翻译为建造者模式或者构建者模式&#xff0c;也有人叫它生成器模式。 在创建对象时&#xff0c;一般可以通过构造函数、set()方法等设置初始化参数&#xff0c;但当参数比较多&#xff0c;或者参数之间有依赖关系&#xff0c;需要进行复杂校验时&a…

Springboot 集成 Seata

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。Seata官网 1.找到适合的Seata版本 参考&#xff1a;SpringCloudAlibaba S…

Linux学习之进程二

目录 进程状态 R (running)运行状态与s休眠状态&#xff1a; disk sleep&#xff08;深度睡眠状态&#xff09; T (stopped)&#xff08;暂停状态&#xff09; t----tracing stop(追踪状态) X死亡状态&#xff08;dead&#xff09; Z(zombie)-僵尸进程 孤儿进程 进程优…

python捕获异常和scapy模块的利用

Python捕获异常 ​ 当程序运行时&#xff0c;因为遇到未知的错误而导致中止运行&#xff0c;便会出现Traceback 消息&#xff0c;打印异常。异常即是一个事件&#xff0c;该事件会在程序执行过程中发生&#xff0c;影响程序的正常执行。一般情况下&#xff0c;在Python 无法正…

2023年Q3户外装备市场行业分析报告(京东数据分析):同比增长7%,品牌化发展是核心

近年来&#xff0c;户外运动在我国不少地方蓬勃兴起&#xff0c;发展至今&#xff0c;户外运动早已不是聚焦专业领域的小众群体活动&#xff0c;现已发展成为当下热门的大众休闲活动&#xff0c;参与人群愈发广泛&#xff0c;而这股热潮也带动着相关产业的发展。 今年Q3&#x…

IT老鸟给开发者升职加薪的小技巧

前言&#xff1a; 升职加薪对大多数人来说都是工作重要动力所在&#xff0c;但总存在“青出于蓝而胜于蓝”&#xff0c;后来人居上的情况。很多人不清楚&#xff0c;自己兢兢业业&#xff0c;任劳任怨&#xff0c;到头来还是得不到领导的重视&#xff0c;身边一起过来的同事都成…

GZ035 5G组网与运维赛题第7套

2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项&#xff08;高职组&#xff09; 赛题第7套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通&#xff08;35分&#xff09; 子任务1&#xff1a;5G公共网络部署与调试&#xff08;15分&#xff09; 子…

单元测试到底测什么,怎么测?我来告诉你

前言&#xff1a; 以国内互联网的开发节奏&#xff0c;在前端业务项目中全面覆盖单元测试有时显得不太可行&#xff0c;主要是因为以下这些绊脚石&#xff1a; UI 交互复杂&#xff0c;路径难以覆盖全面 工期紧&#xff0c;开发对实践 TDD&#xff0c;BDD 所带来的长远效益没有…

Arduino开发

文章目录 资源Arduino IDE 的使用1. 使能编译以及烧录的LOG&#xff1a;2. 下载配置3. 下载 Arduino指令程序下载步骤通过下载器下载通过串口下载 关于Arduino IDE工程生成的二进制文件对比Tools-->burn bootloader 和 ArduinoISP例程 的区别自带例程 资源 Arduino通过串口…

解决MySQL大版本升级导致.Net(C#)程序连接报错问题

数据库版本从MySQL 5.7.21 升级到 MySQL8.0.21 数据升级完成后&#xff0c;直接修改程序的数据库连接配置信息 <connectionStrings> <add name"myConnectionString" connectionString"server192.168.31.200;uidapp;pwdFgTDkn0q!75;databasemail;&q…

【缓存】Spring全家桶中@CacheEvict无效情况共有以下几种

Spring全家桶中CacheEvict无效情况共有以下几种 一、背景介绍二、原因分析三、解决方案 一、背景介绍 SpringBoot中使用Cacheable注解缓存数据&#xff0c;使用CacheEvict注解删除缓存。但是在项目使用过程中&#xff0c;发现使用CacheEvict注解删除缓存无效。 拓展&#xff…