leetcode-哈希表

news2024/12/26 13:40:49

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存的,还是不行

在这里插入图片描述

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

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

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

相关文章

leetcode 1353. 最多可以参加的会议数目

给你一个数组 events&#xff0c;其中 events[i] [startDayi, endDayi] &#xff0c;表示会议 i 开始于 startDayi &#xff0c;结束于 endDayi 。 你可以在满足 startDayi < d < endDayi 中的任意一天 d 参加会议 i 。注意&#xff0c;一天只能参加一个会议。 请你返回…

面试测试工程师一般问什么问题?

面试和项目一起&#xff0c;是自学路上的两大拦路虎。面试测试工程师一般会被问什么问题&#xff0c;总结下来一般是下面这4类&#xff1a; 1.做好自我介绍 2.项目相关问题 3.技术相关问题 4.人事相关问题 接下来&#xff0c;主要从以上四个方向分别展开介绍。为了让大家更有获…

【多线程面试题十三】、说一说synchronized与Lock的区别

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;说一说synchronized与Lo…

使用Python获取建筑网站数据,进行可视化分析,并实现网站JS解密

哈喽兄弟们&#xff0c;今天来实现一下建筑市场公共服务平台的数据采集&#xff0c;顺便实现一下网站的JS解密。 话不多说&#xff0c;我们直接开始今天的内容。 首先我们需要准备这些 环境使用 Python 3.8Pycharm 模块使用 requests --> pip install requestsexecjs -…

scratch图书的ISBN码校验 2023年9月中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析

目录 scratch图书的ISBN码校验 一、题目要求 1、准备工作 2、功能实现 二、案例分析

10 MIT线性代数-四个基本子空间 four fundamental subspaces

1. 四个子空间 Four subspaces (mxn) 列空间 Column space C(A) in 零空间Nullspace N(A) in 行空间Row space all combs of rows all combs of columns of AT C(AT) in 左零空间Left nullspace Nullspace of AT N(AT) left nullspace of A in 2. 基和维数 Basis&…

【Qt之QLocale】使用

描述 QLocale类可以在多种语言之间进行数字和字符串的转换。 QLocale类在构造函数中使用语言/国家对进行初始化&#xff0c;并提供类似于QString中的数字转字符串和字符串转数字的转换函数。 示例&#xff1a; QLocale egyptian(QLocale::Arabic, QLocale::Egypt);QString s1 …

分布式:一文吃透分布式事务和seata事务

目录 一、事务基础概念二、分布式事务概念什么是分布式事务分布式事务场景CAP定理CAP理论理解CAPCAP的应用 BASE定理强一致性和最终一致性BASE理论 分布式事务分类刚性事务柔性事务 三、分布式事务解决方案方案汇总XA规范方案1&#xff1a;2PC第一阶段&#xff1a;准备阶段第二…

ubuntu部署个人网盘nextCloud使用docker-compose方式

概述 当下各大网盘的容量都是有限制的&#xff0c;而且xx云不开会员网速就拉跨。 所以就想搭建一个自己的盘&#xff0c;并且可以控制用户的权限分组&#xff1b; nextCloud就很合适 我这边都是自己用偶尔给其他人使用下&#xff0c;所以直接docker部署了。 ubuntu版本&…

【面试经典150 | 栈】逆波兰表达式求值

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;栈方法二&#xff1a;使用数组模拟栈 知识点拨两个概念中缀表达式转后缀表达式后缀表达式计算四则运算表达式例题 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文…

时序预测 | Python实现ARIMA-LSTM差分自回归移动平均模型结合长短期记忆神经网络时间序列预测

时序预测 | Python实现ARIMA-LSTM差分自回归移动平均模型结合长短期记忆神经网络时间序列预测 目录 时序预测 | Python实现ARIMA-LSTM差分自回归移动平均模型结合长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 时序预测 | Python实现ARIM…

闭包的理解?一般使用场景

是什么 一个函数和对其周围状态(词法环境)的引用捆绑在一起(函数被引用包围)&#xff0c;这样的组合我们称之为闭包 也就是说&#xff0c;闭包让你可以在一个内层函数中访问到其外层函数的作用域 &#x1f356;在 JavaScript中&#xff0c;每当创建一个函数&#xff0c;闭包…

Java SE 学习笔记(十七)—— 单元测试、反射

目录 1 单元测试1.1 单元测试概述1.2 单元测试快速入门1.3 JUnit 常用注解 2 反射2.1 反射概述2.2 获取类对象2.3 获取构造器对象2.4 获取成员变量对象2.5 获取常用方法对象2.6 反射的作用2.6.1 绕过编译阶段为集合添加数据2.6.2 通用框架的底层原理 1 单元测试 1.1 单元测试概…

Java字节码创建对象指令

接上节。 示例代码&#xff1a; package com.lkl.jvmDemo;public class HelloByteCode {public static void main(String[] args) {HelloByteCode obj new HelloByteCode();} }查看字节码清单javap -c -verbose HelloByteCode Classfile /XXX/com/lkl/jvmDemo/HelloByteCod…

【电路笔记】-交流电阻和阻抗

交流电阻和阻抗 文章目录 交流电阻和阻抗1、概述&#xff1a;电阻率2、交流状态与直流状态近似性3、交流状态与直流状态的差异性3.1 趋肤效应(The Skin Effect)3.2 靠近效应&#xff08;The Proximity Effect&#xff09; 4、总结 电阻是一种特性&#xff0c;用于表征当电压差施…

2023最流行的自动化测试工具有哪些?

一&#xff1a;前言 随着测试工程师技能和工资待遇的提升&#xff0c;甚至有一部分的开发人员开始转入测试岗位&#xff0c;跨入自动化领域的测试攻城狮越来越多。在自动化测试领域&#xff0c;自动化工具肯定占据了核心的位置。 本文总结了常用的测试自动化工具和框架&#x…

【机器学习可解释性】5.SHAP值的高级使用

机器学习可解释性 1.模型洞察的价值2.特征重要性排列3.部分依赖图4.SHAP 值5.SHAP值的高级使用 正文 汇总SHAP值以获得更详细的模型解释 总体回顾 我们从学习排列重要性和部分依赖图开始&#xff0c;以显示学习后的模型的内容。 然后我们学习了SHAP值来分解单个预测的组成部…

汇编语言-div指令溢出问题

汇编语言-div指令溢出问题 8086CPU中被除数保存在ax(16位)或ax和dx&#xff08;32位&#xff09;中&#xff0c;如果被除数为16位&#xff0c;进行除法运算时al保存商&#xff0c;ah保存余数。如果被除数为32位时&#xff0c;进行除法运算时&#xff0c;ax保存商&#xff0c;d…

从最简单基本开始 or 把问题复杂化还自诩为“设计了一个可扩展的系统”?

文章目录 Intro程序员“把问题复杂化”的职业病如何抉择 Intro 刚才看了一段关于在苹果系统中使用numbers表格软件制作记账本的视频教程&#xff1a;当 Excel 交给苹果来设计会变成…&#xff1f;#Numbers 新手教学&#xff0c;以下为最终界面效果&#xff1a; 有些触动&…

网络原理续

传输层的协议也并非就只有UDP和TCP 就拿王者荣耀这个游戏来说 是否需要可靠性是否需要高效率 那是使用TCP还是UDP呢? 当然是都不用, 除了这两个协议外, 有的传输层协议就是为游戏场景量身打造的. 比如说以KCP为代表的一系列协议. 网络层 地址管理路由选择 网络层的代表:…