当前位置: 首页 > news >正文

【代码随想录训练营第42期 Day7打卡 LeetCode 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

目录

一、做题心得

二、题目及题解

454.四数相加II 

题目链接

题解

383. 赎金信

题目链接

题解

15. 三数之和 

题目链接

题解

18. 四数之和

题目链接

题解

三、小结


一、做题心得

今天是代码随想录训练营打卡的第七天,做的也是同昨天一样的哈希表部分。感觉得出题目难度有所增大,然后我自己的话,最后两个题哈希的方法过于繁琐,做的时间有些久了,放弃了。后边通过题解,慢慢搞懂了双指针的做法(后两个题思路基本一样)。话不多说,直接开始看题。

二、题目及题解

454.四数相加II 

题目链接

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

题解

首先说说暴力吧,这个题其实一眼就能看出暴力解法,但也很显然,时间复杂度过高,肯定过不了所有用例。我试着敲了一下,大家可以看看结果,如下:

然后各位可以回想一下,昨天打卡的两数之和(1. 两数之和 - 力扣(LeetCode))那道题,是不是感觉有一些相似。只不过这里变成了四个数组对应的四个值,所以我们要采用分组的思路。把i+j看成一体,把k+l看成一体,用和昨天差不多思路,定义unordered_map<key,value>型哈希表,其中key为i+j的具体的值(和),value为该值出现的次数。对a+b所有可能及其值存储到哈希表中,再通过查找函数等等操作得出结果。(还是不理解的话可以去看看昨天打卡的1.两数之和那道题)

代码如下:

//分组+哈希
class Solution {
public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {unordered_map<int,int> hash;    //在这里key为i+j的具体的值(和),value为该值出现的次数int cnt = 0;      //记数for(int i : nums1)          //先存储i+j的值及其对应的个数到哈希表中{for(int j : nums2 ){hash[i+j]++;}}for(int k : nums3){for(int l : nums4){if(hash.find(0 - k - l) != hash.end())     //若hash表中存在满足和为0-k-l的i+j时,cnt加上满足的i+j的个数cnt += hash[0 - k - l];}}return cnt;}
};

383. 赎金信

题目链接

383. 赎金信 - 力扣(LeetCode)

题解

这个题感觉和昨天那个242. 有效的字母异位词 - 力扣(LeetCode)一模一样,比较简单,相信大家都能解决,不会的话可以看看我昨天的打卡或者去搜索巩固一下哈希的基本知识。

代码如下:

class Solution {
public:bool canConstruct(string ransomNote, string magazine) {unordered_map<char,int> hash;for(char ch : magazine){hash[ch]++;}for(char ch : ransomNote){hash[ch]--;if(hash[ch] < 0)      return false;}return true;}
};//分析:由于ransomNote中的元素都能被magazine包含,故ransomNote出现的每一个元素的个数都少于在magzine出现的次数,即原本hash[ch]++后再减也应该大于等于0

15. 三数之和 

题目链接

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

题解

这个题我感觉作为第一次做还是挺有难度的。如果用哈希做的话,很容易出错,时间上讲也不如双指针来的快。所以这里我们统一学习一下“排序+双指针”的思路。(由于下一道题与这个差不多,我把题解都写在这里,希望不会的各位可以认真看一下下边步骤并结合一下代码思考)

先分析题意,我们将要得到的三个数记作a,b,c(最后分别对应着nums[i],nums[left],nu ms[right])

然后进行以下步骤:
1.初始化结果向量:首先,初始化一个vector<vector<int>>类型的变量ans,用来存储所有满足条件的三元组。
2.排序:对输入的数组nums进行排序,这是为了使用双指针法,并且能够方便地去除重复解。
3.遍历数组:使用一个外层循环遍历数组nums,每次迭代中,当前元素记为a(即nums[i])。
4.去重a:在遍历过程中,如果当前元素a与前一个元素相同,则跳过本次循环(因为前面的迭代中已经考虑过这种情况了,不需要重复计算)。这里需要注意的是,去重a的逻辑应该放在i > 0的条件下,以避免在数组开头漏掉可能的解。
5.双指针法:在内层,使用两个指针left和right,分别指向a之后的第一个元素和数组的最后一个元素。然后,根据三数之和与0的比较结果,移动这两个指针来寻找满足条件的三元组。
6.去重b和c:当找到一个满足条件的三元组时,需要去除b和c(即nums[left]和nums[right])的重复值。这是通过移动指针,跳过与当前b或c相同的元素来实现的。这一步必须放在将当前三元组添加到ans之后进行,以确保不会漏掉任何可能的解。
7.返回结果:当遍历完整个数组后,返回存储了所有满足条件的三元组的ans。

代码如下:(有注释)

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(), nums.end());     //先排序vector<vector<int>> ans;        //由于数组元素为数组,故用嵌套vector存储结果int n = nums.size();if (n < 3)      //特殊情况先考虑return ans;for (int i = 0; i < n - 2; i++) {if (nums[i] > 0) break;                     //提前终止if (i > 0 && nums[i] == nums[i - 1]) continue;      //去重a,避免重复解if (nums[i] + nums[i + 1] + nums[i + 2] > 0) break;     //由于数组已经排过序了,这时不可能存在满足的了,提前终止if(nums[i] + nums[n-1] + nums[n-2] < 0)    continue;    //此时说明a(nums[i])小了,直接返回循环,i+1。(这样可以节省时间,直接跳过后续步骤。)int left = i + 1, right = n - 1;    //使用两个指针left和right,分别指向nums[i]之后的第一个元素和数组的最后一个元素while (left < right) {int sum = nums[i] + nums[left] + nums[right];   //注意sum为a,b,c的和if (sum == 0) {         //满足要求时ans.push_back({ nums[i],nums[left],nums[right] });  //先存入结果while (left < right && nums[left] == nums[left + 1])    left++;  //移动左指针去重b(注意是while语句)while (left < right && nums[right] == nums[right - 1])  right--; //移动右指针去重cleft++;         //每次存放结果后,双指针都移动一位,便于后续下一步判断right--;}else if (sum < 0) left++;         //如果和小于0, 向右移动左指针else right--;       //如果和大于0, 向左移动右指针}}return ans;}
};

18. 四数之和

题目链接

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

题解

由于和上道题思路差不多,这里可以直接看代码:(代码可能感觉有些长,但是思路其实很清晰,注意看看上一道题的思路和注释,相信你能做出这道题)

class Solution {
public:                  //注意:题目数据要求较大,有些语句要加上longvector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> ans;sort(nums.begin(),nums.end());int n = nums.size();if(n < 4)   return ans;for(int i = 0;i < n - 3;i++){if(i > 0 && nums[i] == nums[i-1])continue;if((long)nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target)     break;if((long)nums[i] + nums[n-1] + nums[n-2] + nums[n-3] <target)continue;for(int j = i + 1;j < n - 2;j++){if(j > i + 1 && nums[j] == nums[j-1])continue;if((long)nums[i] + nums[j] + nums[j+1] + nums[j+2] > target)break;if((long)nums[i] + nums[j] + nums[n-1] + nums[n-2] < target)continue;int left = j + 1;int right = n - 1;while(left < right){long sum = (long)nums[i] + nums[j] + nums[left] + nums[right];if(sum == target){ans.push_back({nums[i],nums[j],nums[left],nums[right]});while(left < right && nums[left] == nums[left+1])left++;while(left < right && nums[right] == nums[right-1])right--;left++;right--;}else if(sum < target)left++;elseright--;}} }return ans;}
};

三、小结

今天的打卡到此也就结束了,感觉自己今天的的确确学到了些新东西,还不错吧。后边也会继续更新代码随想录的打卡,不断学习,不断积累自己。最后,我是算法小白,但也希望终有所获。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Gitlab】SSH配置和克隆仓库
  • 基于FFmpeg和SDL的音视频解码播放的实现过程与相关细节
  • flex:1
  • 利用OSMnx求路网最短路径并可视化(二)
  • 分类常用的评价指标-二分类/多分类
  • 零代码拖拽,轻松搞定GIS场景编辑
  • Linux——DNS服务搭建
  • 甄选范文“论软件测试中缺陷管理及其应用”软考高级论文,系统架构设计师论文
  • 机器学习笔记 第一章绪论
  • 系统架构师(每日一练9)
  • IOS微软语音转文本,lame压缩音频
  • 【目标检测】非极大值抑制(Non-Maximum Suppression, NMS)步骤与实现
  • 超级智能体创造营:启动!我的情侣匹配度测试助手
  • Vue3 reactive原理(一)-代理对象及数组
  • 可乐的由来
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • angular组件开发
  • Computed property XXX was assigned to but it has no setter
  • crontab执行失败的多种原因
  • ECMAScript6(0):ES6简明参考手册
  • GitUp, 你不可错过的秀外慧中的git工具
  • HTTP 简介
  • Java程序员幽默爆笑锦集
  • Java教程_软件开发基础
  • leetcode98. Validate Binary Search Tree
  • MySQL QA
  • Python3爬取英雄联盟英雄皮肤大图
  • 服务器从安装到部署全过程(二)
  • 服务器之间,相同帐号,实现免密钥登录
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 手写一个CommonJS打包工具(一)
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 限制Java线程池运行线程以及等待线程数量的策略
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 阿里云移动端播放器高级功能介绍
  • 积累各种好的链接
  • 整理一些计算机基础知识!
  • ​​​​​​​STM32通过SPI硬件读写W25Q64
  • ​Redis 实现计数器和限速器的
  • ​浅谈 Linux 中的 core dump 分析方法
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • (14)Hive调优——合并小文件
  • (2015)JS ES6 必知的十个 特性
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (python)数据结构---字典
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (接口封装)
  • (算法)硬币问题
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)