代码随想录(day7)——哈希表

Leetcode.454 四数相加Ⅱ:

454. 四数相加 II - 力扣(LeetCode)

       对于本题,虽然使用四层for循环嵌套可以解决,但是效率过慢,为O(n^{4}),因此,可以将给定的四个数组,分成两组,即:nums1,nums2为一组,nums3,nums4为一组,由于题目的要求是找到满足nums1[i]+nums2[j]+nums3[k]+nums4[l]==0的元组的数量,对于这个问题,可以抽象的看成,查找在nums3,nums4中,是否有满足-(nums1[i]+nums[j])的元素。

     因此,可以利用map定义一个哈希表,通过两次for循环嵌套,存放nums1[i]+nums2[j]所有元素组合出现的次数。

     再去利用两层for循环在nums3,nums4进行查找相应的元素。例如,在定义好的哈希表中,nums1[i]+nums2[j]==5的元组出现了4次,因此,需要在nums3,nums4中进行逐次遍历,查找0-(nums3[i]+nums4[j])是否在哈希表中出现过,若出现过,则说明存在符合条件nums1[i]+nums2[j]+nums3[k]+nums4[l]==0的元组,此时再定义一个变量count,令count+=map[0-(nums3[i]+nums4[j])];即可。具体代码对应如下:

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 = 0; i < nums1.size(); i++){for(int j = 0; j < nums2.size(); j++){umap[nums1[i]+nums2[j]]++;}}for(int i = 0; i < nums3.size(); i++){for(int j = 0; j < nums4.size(); j++){if(umap.find(0-(nums3[i]+nums4[j])) != umap.end()){count += umap[0-(nums3[i]+nums4[j])];}}}return count;}
};

运行结果如下:

Leetcode.382 赎金信:

383. 赎金信 - 力扣(LeetCode)

       本题与上篇文章代码随想录(day6)——哈希表-CSDN博客中的题目. - 力扣(LeetCode)相似。都是利用哈希表来统计一个字符串中各个字母出现的次数,再拿去另一个字符串中进行比对。不过对于本题还是需要注意一些细节:

       由于题目中说明,给定的两个字符串全都由小写英文字母构成,因此,直接定义一个大小为26的整型数组即可。

      题目中提到了,需要判断ransomNote能不能由magazine中出现过的字符组成,并且,magazine中出现n次的字符在ransomNote只能使用n次,例如,ransomNoteaaamagazineaa,由于ransomNote中出现a的次数为3magazine中出现a的次数为2,因此判定false。所以,在创建数组进行判断之前,首先判定一次两个字符串的长短关系,如果ransomNote.size() > magazine.size();则直接判定为false即可。

    并且由题干中给出了aa,aab的样例来看,可以得出一个结论:magazine中出现的字符的种类可以>=ransomNote中出现的字符的种类,magazine中单个字符出现的次数必须>=ransomNote中单个字符出现的次数

    介于上面的原理,可以先遍历一次magazine,统计其出现的字符的种类以及单个字符出现的次数即:hash[magazine[i]-'a']++,然后再去遍历ransomNote,令hash[ransomNote[i]-'a']--;如果hash任意位置出现了hash[i]<0,则说明ransomNote出现了magazine中没有的字符或者ransomNote出现某个字符的次数>magazine出现这个字符的次数,返回false。对应代码如下:

class Solution {
public:bool canConstruct(string ransomNote, string magazine) {if(ransomNote.size() > magazine.size()){return false;}int hash[26] = {0};for(int i = 0; i < magazine.size(); i++){hash[magazine[i]-'a']++;}for(int j = 0; j < ransomNote.size(); j++){hash[ransomNote[j]-'a']--;if( hash[ransomNote[j]-'a'] < 0){return false;}}return true;}
};

运行结果如下:

从入门到入土——Leetcode.15 三数之和:

15. 三数之和 - 力扣(LeetCode)

       对于三数之和这道题,相对于两数之和的难度有明显的上升,如果说两数之和作为梦开始的地方,那么三数之和可以说是梦结束的地方。这是因为本题相对于两数之和只需要控制两个变量进行判断变成了需要控制三个变量,并且,题目中要求了答案中不可以包含重复的三元组,例如[-1,1,0],[-1,0,1]就属于两个重复的三元组。

       虽然文章的标题为哈希表,但是对于三数之和,以及后面的四数之和,使用双指针的方法能更加容易的解决问题。具体方法如下:

首先利用vector创建一个二维数组result,用于接收合适的三元组。
       

例如对于题目中给定的数组,首先进行一次排序,即:

       再排序完成后,由于题目要求需要找到三个数的和==0,因此,要么数组中的元素全为0,要么数组中同时存在正数,负数,所以,如果数组的第一个数已经>0,则不可能存在三个数相加等于0的情况,因此直接返回result即可。

      对于本题所使用的双指针法,大致思路如下:

     首先利用循环对每一个元素都进行一次双指针的判定,例如对于数组中的第一个元素-4,令其作为三元组的第一个元素,其下一个元素用left表示,数组的最后一个元素用right表示。

    如果出现了nums[i]+nums[left]+nums[right]>0的情况,由于数组在开始进行了排序,只需要令right--即可。

   如果出现了nums[i]+nums[left]+nums[right]<0的情况,则令left++

   如果出现了nums[i]+nums[left]+nums[right]==0,则说明找到和符合条件的三元组,随后将这个三元组利用result进行保存。

   题目的大致解题思路如上,但是,由于题目要求不能出现的重复的三元组,因此,需要对每个元素进行去重判定,具体操作如下:

    首先是针对每次循环中,头个元素的去重判定:

   首先需要明确,如果确定了三元组中的两个数重复,则三元组一定重复,所以,对于第一个数据而言,需要判定其前一个数是否与自己相等,例如:

如图所示,其前一个数据与自身相等,则一定会造成重复。在这里,或许读者会有一位,为什么要求判定与前一个元素是否相同,即nums[i]==nums[i-1]而不是去判定nums[i]==nums[i+1]。对于这个问题,上图可以给出解释,如果去后一个数相等,则对于下面的情况:

      如果按照nums[i]==nums[i+1]进行判定重复,则在返回的正确的三元组中,会丢失一组数据,即[-1,-1,2]。因此,在判定是否重复时,需要按照nums[i]==nums[i-1]进行判定。如果满足重复的条件,则直接利用continue判定下一个元素即可。

     而对于其余的两个元素,即left,right所代表的元素,则也需要进行去重操作,例如对于下面的操作:

        例如,对于图中的三元组[-4,0,4],在找到后由于left后面的元素和right前面的元素都造成了重复,因此,如果left[i]==left[i+1],则令left++,如果right[i]==right[i-1],则令right--。具体效果如下:

       此时,left,right相邻的元素不造成重复,因此在去重完成后,令left++,right--,来寻找下一组满足条件的三元组。

具体代码如下:

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {//对数组整体排序sort(nums.begin(),nums.end());vector<vector<int>> result;for(int i = 0; i < nums.size();i++){//检测首个元素是否>0if(nums[i] > 0){return result;}//对于首个元素进行去重if(i > 0 && nums[i] == nums[i-1]){continue;}//定义双指针int left = i+1;int right = nums.size()-1;while(left < right){if(nums[i]+nums[left]+nums[right] > 0){right--;}else if(nums[i]+nums[left]+nums[right] < 0){left++;}else{result.push_back(vector<int>{nums[i],nums[left],nums[right]});//对于双指针进行去重while(left < right && nums[right] == nums[right-1]){right--;}while(left < right && nums[left] == nums[left+1]){left++;}right--;left++;}}}return result;}
};

Leetcode.18 四数之和:

18. 四数之和 - 力扣(LeetCode)

对于本题,主题思路与三数之和大致相同。具体如下:

        在三数之和中,如果第一个元素>0,则说明不存在三元组使得三元组中元素的和==0,但是需要注意,在本题中,是给定一个targettarget可以<0。因此,在进行判断时,需要进行两次判断,即:(nums[i]>0&&target>0)如果满足,则说明,在数组中不存在合适的四元组使得其中四个数之和等于target,随后需要对这个元素进行去重,去重的方法相同,即nums[i]==nums[i-1]

       随后,令k=i+1,即:

将这两个数加和进行一次判断,即nums[i]+nums[k] > 0&&target>=0。随后,再对k位置的数据进行去重操作。

此时,前面的两个数据可以看作一个整体,最后再使用三数之和中的双指针法,即:

最后进行类似于三数之和一样的操作。本处不再展开说明,只给出代码:
 

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> result;sort(nums.begin(),nums.end());for(int k = 0; k < nums.size(); k++){if(nums[k] > target && nums[k] >= 0){break;}if(k > 0 && nums[k] == nums[k-1]){continue;}for(int i = k+1; i < nums.size(); i++){if(nums[i] + nums[k] > target && nums[i]+nums[k] >= 0){break;}if(i > k+1 && nums[i] == nums[i-1]){continue;}int left = i+1;int right = nums.size()-1;while(left < right){if((long)nums[i] + nums[k] +nums[left] +nums[right] > target){right--;}else if((long)nums[i] + nums[k] +nums[left] +nums[right] < target){left++;}else{result.push_back(vector<int>{nums[i],nums[k],nums[left],nums[right]});while(left < right && nums[right] == nums[right-1]){right--;}while(left < right && nums[left] == nums[left+1]){left++;}right--;left++;}}}}return result;}
};

运行结果如下:

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

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

相关文章

在服务器上配置源和安装anaconda

在服务器上配置源和安装anaconda解决无法import torch的方法&#xff1a; 一、在 anaconda上创建环境 1、创建环境 conda create -n yourname pythonx.x 2、查看环境 conda info --envs 3、进入环境 source activate your_env_name 4、退出环境 conda deactivate 5、…

程序计数器

程序计数器 JVM中的程序计数器(Program Counter Register)并非是广义上所指的物理寄存器&#xff0c;是对物理PC寄存器的一种抽象模拟 PC寄存器(程序计数器) PC寄存器用来存储指向下一条指令的地址&#xff0c;也即将要执行的指令代码。由执行引擎读取下一条指令。 它是一块很…

Adams Car——Adams car与Simulink联合仿真

1.修改悬架阻尼、刚度 ①先找到车辆悬架阻尼和刚度文件,这里以阻尼显示为例 ②修改阻尼曲线 找到对应车的文件 ③修改完后进行替换,刚度修改同理 2.转动惯量与车的质量修改

【晶振选型】VCTCXO TCXO 布线 参考

一、供电旁路电容 二、使能信号 三、输出的交流耦合 四、输出波形转换 五、压控滤波电容 最后 CTS的是真不错&#xff0c;1K可是-140啊

Linux---基本操作命令之用户管理命令

1.1useradd 添加新用户 root用户&#xff1a;/root 普通用户&#xff1a;/home/ 创建的用户还是david&#xff0c;只是在dave文件夹下 1.2 passwd 设置密码 给用户tony设置密码: 123456 1.3 id 查看用户是否存在 查看有没有这个用户&#xff1a;id 名字 gid&#xff1a;用…

Spring MVC文件下载配置

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 文件下载 在Spring MVC中通常利用commons-io实现文件下载&#xff0c;示例代码如下&#xff1a; Controller RequestMapping("......") public class DownloadC…

外卖项目:使用AOP切面编程实现增删改查的操作日志记录(debug断点调试)

文章目录 一、问题描述二、问题分析三、断掉调试四、代码展示 一、问题描述 需求&#xff1a;将项目中增、删、改相关接口的操作日志记录到数据库表中。 操作日志信息包含&#xff1a; 操作人、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时…

MySQL数据库基本操作和管理

目录 一.MySQL数据库基本操作 1.SQL分类 &#xff08;1&#xff09;数据库&#xff1a;database &#xff08;2&#xff09;表&#xff1a;table&#xff0c;行&#xff1a;row 列&#xff1a;column &#xff08;3&#xff09;索引&#xff1a;index &#xff08;4&…

Linux网络编程: TCP协议首部与可选项简述

一、TCP/IP五层模型 物理层&#xff08;Physical Layer&#xff09;&#xff1a;物理层是最底层&#xff0c;负责传输比特流&#xff08;bitstream&#xff09;以及物理介质的传输方式。它定义了如何在物理媒介上传输原始的比特流&#xff0c;例如通过电缆、光纤或无线传输等。…

python中字典相关知识点总结

1.字典的定义 字典&#xff1a;在Python中&#xff0c;字典是一系列键-值对。每个键都与一个值相关联&#xff0c;程序员可以通过键来访问与之相关联的值。 实际举例&#xff1a; student{name:xincun,age:18} 通过实例我们可以发现&#xff0c;键-值对是两个相关联的值。指…

CodeWhisperer插件

一、前言 产品官网地址&#xff1a;What is CodeWhisperer? - CodeWhisperer Amazon CodeWhisperer 是一个通用的、由机器学习驱动的代码生成器&#xff0c;可实时为您提供代码建议。在您编写代码时&#xff0c;CodeWhisperer 会根据您现有的代码和注释自动生成建议。您的个…

机器人路径规划:基于斑翠鸟优化算法(Pied Kingfisher Optimizer ,PKO)的机器人路径规划(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人&#xff08;Mobile robot&#xff0c;MR&#xff09;的路径规划是 移动机器人研究的重要分支之&#xff0c;是对其进行控制的基础。根据环境信息的已知程度不同&#xff0c;路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…

mysql 数据库 增删改查 基本操作

目录 一 SQL 详细介绍 &#xff08;一&#xff09;SQL 分类 &#xff08;二&#xff09; SQL 语言规范 &#xff08;三&#xff09;数据库对象和命名 1&#xff0c;数据库的组件(对象)&#xff1a; 2&#xff0c;命名规则&#xff1a; &#xff08;四&#xff09; SQL…

使用Python查找字符串中包含的多个元素

目录 一、引言 二、基本字符串操作 使用in关键字查找子字符串 使用循环和条件判断查找多个子字符串 三、使用正则表达式进行高级搜索 导入re模块 使用re.search()查找单个模式 使用re.findall()查找多个模式 四、案例与代码 五、优化与扩展 六、总结 一、引言 在Py…

【5G NB-IoT NTN】3GPP R17 NB-IoT NTN介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

20万买新能源,除了烂大街的车,还可以选“精而美”

美”文 | AUTO芯球 作者 | 雷歌 “旧车撞了&#xff0c;准备买新车”。 前几天老家一个同学发来消息&#xff0c;春节他追尾了别人的车&#xff0c;不光赔了钱&#xff0c;还把自己的车车头撞废了&#xff0c;修好得一大笔钱&#xff0c;他干脆当废铁1万块钱卖给二手车商了。…

我的自建博客之旅06之Mrdoc

这个是我折腾笔记项目的最后一篇文章了,这个项目是类似于语雀的文档笔记项目,因为我当初想找一个既可以当做笔记,又可以作为团队文档分享的笔记,除了语雀,就发现了这个项目。 这个开源项目的界面或者文档组织方式其实是我最喜欢的,但是我后来放弃它的原因是它的后台编辑逻…

React Native:跨平台移动应用开发的利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

nginx学习记录-目录结构及基本配置

1. nginx目录结构 执行tree命令就可以看到nginx的目录结构了&#xff0c;主要有4个&#xff0c;分别是配置目录conf&#xff0c;还有界面目录html&#xff0c;日志目录logs以及程序sbin/nginx。 2. nignx基本配置 nginx的主要配置文件为/usr/local/nginx/conf/nginx.conf&…

matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面

1、内容简介 略 65-可以交流、咨询、答疑 2、内容说明 matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面 李雅普洛夫指数谱、相图、分岔图、庞加莱界面 3、仿真分析 略 4、参考论文 略