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

news2024/11/15 3:21:58

目录

一、做题心得

二、题目及题解

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--; //移动右指针去重c
                    left++;         //每次存放结果后,双指针都移动一位,便于后续下一步判断
                    right--;
                }
                else if (sum < 0) 
                    left++;         //如果和小于0, 向右移动左指针
                else 
                    right--;       //如果和大于0, 向左移动右指针
            }
        }
        return ans;
    }
};

18. 四数之和

题目链接

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

题解

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

class Solution {
public:                  //注意:题目数据要求较大,有些语句要加上long
    vector<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++;
                    else
                        right--;
                }
            } 
        }
        return ans;
    }
};

三、小结

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

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

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

相关文章

电源防反接电路设计——NMOS管

电源电压接入正确时&#xff0c;由于MOS管中的寄生二极管的存在&#xff0c;从而使得MOS管的Vgs电压为输入电压减去寄生二极管压降电压0.7V&#xff0c;这个电压是大于MOS开关导通的阈值电压&#xff0c;从而使MOS管导通&#xff0c;导通后相当于寄生二极管被MOS管导通短路&…

HVV | .NET 攻防工具库,值得您拥有!

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

Python:随机数、随机选择的应用

step1:导入 导入的random相当于是创建了random文件里的的一个对象 import random random() 产生0~1随机数 randint(a,b)产生a~b的整数 闭区间&#xff0c;可以取到a,b random.choice(touple_name)从touple_name&#xff08;数组、列表..&#xff09;中随机选择元素 import rand…

代码的魔力:Jupyter Notebook从零开始的探索之旅

1. Jupyter Notebook&#xff1a;探索无限的可能 1.1 Jupyter Notebook的简介 Jupyter Notebook是一个开源的Web应用程序&#xff0c;让你能够创建和共享文档&#xff0c;这些文档可以包含实时代码、数学方程、可视化以及叙述性文本。其名字来源于它支持的三种核心编程语言&am…

【管理咨询宝藏147】顶级人力咨询公司创业公司股权与激励模式设计方案

【管理咨询宝藏147】顶级人力咨询公司创业公司股权与激励模式设计方案 【格式】PDF版本 【关键词】薪酬激励、股权设计、股权架构 【核心观点】 - 价值分享型的机制的激励导向非常明确&#xff0c;引导激励对象高度关注财务指标的达成。个别情况下&#xff0c;公司考虑到指标结…

【数据结构】逆波兰计算器的分析和实现

思路分析 从左至右扫描表达式&#xff0c;遇到数字时&#xff0c;将数字压入堆栈&#xff0c;遇到运算符时&#xff0c;弹出栈顶的两个数&#xff0c;用运算符对他们做相应的计算&#xff08;栈顶元素和次顶元素&#xff09;&#xff0c;并将结果入栈&#xff1b;重复上述过程…

day12-文件属性

01.知识点回顾 文件的详细属性 1.inode号->磁盘1.df -i ->inode内存2.df -h ->磁盘内存 2.文件的属性- 普通文件d 目录l 软连接->win的快捷方式c 字节文件->win驱动文件b 硬件/dev/null$? 判断上一条命令执行结果/dev/zero 3.权限rwxrwxrwxr 读w 写x 执行 4.硬…

前端工程化11-webpack常见插件

1、webpack的插件Plugin 刚才我们也讲解了下&#xff0c;我们对webpack路径的一个处理&#xff0c;处理的话包括别名的配置&#xff0c;模块是如何找到并加载的&#xff0c;总的来说到现在webpack这个配置到现在来说还是相当的麻烦的&#xff0c;但是目前来说我们讲的这些东西…

重生奇迹MU自由选择个性大师之路

自由选择大师技能 每一个大师职业都拥有三条大师技能树&#xff0c;每一条大师技能树对职业加强的侧重点各不相同。玩家可以根据自己喜欢专一选择&#xff0c;一条路走到底&#xff1b;当然也可以同时兼修两条或者三条技能树&#xff0c;做到雨露均沾。每一种选择都没有绝对的…

Python 环境管理大师:Virtualenv

文章目录 **Python 环境管理大师&#xff1a;Virtualenv****第一部分&#xff1a;背景介绍****第二部分&#xff1a;Virtualenv 是什么&#xff1f;****第三部分&#xff1a;如何安装 Virtualenv&#xff1f;****第四部分&#xff1a;Virtualenv 基本使用方法****第五部分&…

查找的介绍

目录 一、基本介绍 1、查找方法有&#xff1a; 2、在Python中&#xff0c;我们应当掌握两种常见的查找方法&#xff1a; 二、顺序查找 1、顺序查找案例 2、扩展&#xff1a; 三、二分查找 1、二分查找案例 2、二分查找的思路分析 3、代码实现 一、基本介绍 1、查找方…

Pytorch框架之神经网络

一、全连接神经网络的整体结构 二、全连接神经网络的单元结构 找出一组w,b使得结果最优 三、常见激活函数 四、前向传播 学习率是指训练模型时每次迭代更新模型参数的步长。 五、梯度下降法 六、反向传播计算 七、总结 1、准备数据 2、搭建模型 3、开始训练(设置学习率、…

springboot高校计算机专业学习资料共享平台-计算机毕业设计源码24752

摘 要 在信息化、数字化的时代背景下&#xff0c;教育资源的共享与高效利用已成为推动教育现代化的关键。高校作为培养未来人才的重要基地&#xff0c;其计算机专业的学习资料共享显得尤为重要。这些资料不仅涵盖了基础理论知识&#xff0c;还涉及前沿技术、实践项目和行业经验…

Java --方法引用

方法引用 把已经有的方法拿过来用&#xff0c;当做函数式接口中抽象方法的方法体 1.什么是方法引用? 当做函数式接口中抽象方法的方法体把已经存在的方法拿过来用&#xff0c; 2.::是什么符号? 方法引用符 3.方法引用时要注意什么? 需要有函数式接口 被引用方法必须已经存在…

32单片机开发bootloader程序

一&#xff0c;单片机为什么要使用bootloader 1、使用bootloader的好处 1) 程序隔离&#xff1a;可以同时存在多个程序&#xff0c;只要flash空间够大&#xff0c;或者通过外挂flash&#xff0c;可以实现多个程序共存&#xff0c;在多个程序之间切换使用。 2&#xff09;方便程…

python-小李帮老师改错(赛氪OJ)

[题目描述] 老师给小理发了一封电子邮件&#xff0c;任务如下。 写一个程序&#xff0c;给你 n 个数&#xff0c;输出 X。Xnum1p1​​num2p2​​⋯numnpn​​。 num1​&#xff0c;num2​&#xff0c;⋯⋯&#xff0c;numn​ 都是整数&#x…

探索Python监控之眼:watchdog库深度解析

文章目录 探索Python监控之眼&#xff1a;watchdog库深度解析1. 引言&#xff1a;为何选择watchdog&#xff1f;2. watchdog简介3. 安装watchdog库4. 基本函数与使用方法4.1 初始化监控器4.2 监控文件的创建4.3 监控文件的删除4.4 监控目录的创建4.5 监控目录的删除 5. 场景应用…

神奇的方法解决Navicat闪退

原因 打开Navicat操作上面的工具等就会闪退&#xff0c;原因竟然是屏幕划词&#xff01;&#xff01;&#xff01; 解决方法 看别人提到有道词典的划词功能的原因 我没有安装有道词典&#xff0c;但我安装豆包&#xff0c;它也有划词翻译的功能&#xff0c;关闭即可

【JAVA】记录一次前端无能造成的 线上bug

有一个需求是 当方式切换 垫资时 清空 当前所选细单商品 但是前端的奇葩 操作是&#xff0c;只是在页面上清空 细单。 不请求 后台删除 细单 让前端 必须 清空同时 请求后台 删除细单 但是 该前端 技术不行&#xff0c; 嫌麻烦 不做 只好 后台 判断该类型时 进行删除操作…

分省、地级市数字经济专利数据(1985-2022年)

数据年份&#xff1a;1985-2022年 参考文献&#xff1a;孙勇,张思慧,赵腾宇等.数字技术创新对产业结构升级的影响及其空间效应——以长江经济带为例[J].软科学,2022,36(10):9-16. 包含指标&#xff1a; 地级市数据&#xff1a;省份、地级市、会计年度、当年申请的数字经济相…