代码随想录(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,一经查实,立即删除!

相关文章

【NC16783】拼数

题目 拼数 自定义字符串排序 思路 经过观察可以知道&#xff1a;越高位的数越大&#xff0c;这个数就应该排在越前面的位置&#xff0c;比如 4321 4321 4321 和 4331 4331 4331&#xff0c;则 4331 4331 4331 应该排在前面。 所以将给出的整数转为字符串更容易操作。 将数…

在服务器上配置源和安装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、…

广播接收不到

BroadcastQueue: Background execution not allowed: receiving Intent 最主要是要制定包名

程序计数器

程序计数器 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; 操作人、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时…

WebRTC实现部署到局域网

前面已经实现了一对一视频、一对多视频和一对多虚拟视频&#xff0c;所以&#xff0c;这节就来试试把前面做好的项目部署到局域网上&#xff0c;边学边用才能让自己干劲十足。 粉丝福利&#xff0c; 免费领取C音视频学习资料包学习路线大纲、技术视频/代码&#xff0c;内容包括…

银河麒麟服务器系统中intel-x710网卡丢包问题

银河麒麟服务器系统中intel-x710网卡丢包问题 一 系统环境二 问题描述三 问题分析过程3.1 查看网卡配置文件3.2 netstat -ni查看丢包和重传3.3 使用ethtool -S {网卡名}查看drop3.4 使用sar -n DEV查看丢包情况3.5 使用sar -n ETCP 1查看重传情况3.6 查看/proc/net/snmp中&…

python内置函数 N

python内置函数 N Python 解释器内置了很多函数和类型&#xff0c;任何时候都能使用。 N 名称描述next返回迭代器中的下一个元素。 next(iterator) next(iterator) next(iterator, default) next()是一个内置函数&#xff0c;用于从迭代器中获取下一个项目。它通常与迭代…

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&…

Resilience4j原理及应用:构建高可用性系统的熔断、限流与容错机制(一)

本系列文章简介&#xff1a; 在本系列文章中&#xff0c;我们将深入探讨Resilience4j的原理及应用&#xff0c;包括熔断器、限流器和容错策略的工作原理、配置方法以及最佳实践。通过学习和掌握Resilience4j的使用技巧&#xff0c;我们将能够更好地构建高可用性系统&#xff0c…

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;键-值对是两个相关联的值。指…

如何实现数据库的主从复制?

如何实现数据库的主从复制&#xff1f; 数据库的主从复制是实现数据备份、负载均衡和故障恢复的重要策略。它涉及一个主数据库&#xff08;Master&#xff09;和一个或多个从数据库&#xff08;Slave&#xff09;&#xff0c;主数据库负责处理写入操作&#xff0c;而从数据库则…

代码随想录算法训练营第二十九天|491.递增子序列、46.全排列、47.全排列 II

文档讲解&#xff1a;491.递增子序列、46.全排列、47.全排列 II 题目链接&#xff1a;491.递增子序列、46.全排列、47.全排列 II 491.递增子序列 class Solution {List<List<Integer>> res new ArrayList<>();List<Integer> path new ArrayList<…

CodeWhisperer插件

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

JAVA 100道题(6)

6.创建一个表示矩形的类&#xff0c;包括宽度和高度属性&#xff0c;以及计算面积和周长的方法。 下面是一个简单的Python类&#xff0c;表示矩形&#xff0c;包含宽度和高度属性&#xff0c;以及计算面积和周长的方法&#xff1a; python复制代码 class Rectangle: def __ini…