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

代码随想录第七天|● 454.四数相加II ● 383. 赎金信 ● 15. 三数之和 18.四数之和

 本文所有题目链接/文章讲解/视频讲解:https://programmercarl.com/0454.%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0II.html

454.四数相加II

有四个数组,如果要遍历则时间复杂度太大
可以选择分组,a和b一组,c和d一组
这样就可以等同于两个数之和为0的情况了
只需要把a+b的所有可能和放入哈希表,然后c和d的和再找哈希表里能和它们加和等于0的
哈希表使用map,一个表示ab的和,一个表示次数

class Solution {
public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {//有四个数组,如果要遍历则时间复杂度太大//则可以选择分组,a和b一组,c和d一组//这样就可以等同于两个数之和为0的情况了//只需要把a+b的所有可能和放入哈希表,然后c和d的和再找哈希表里能和它们加和等于0的//哈希表使用map,一个表示ab的和,一个表示次数unordered_map<int,int> m;for(int i=0;i<nums1.size();i++){for(int j=0;j<nums2.size();j++){m[nums1[i]+nums2[j]]++;}}int count=0;for(int i=0;i<nums3.size();i++){for(int j=0;j<nums4.size();j++){int s=-(nums3[i]+nums4[j]);if(m.find(s)!=m.end()){count+=m[s];}}}return count;}
};

383. 赎金信

本题 和 242.有效的字母异位词 是同样类型的题目,思路都是一样的,使用数组做哈希表

class Solution {
public:bool canConstruct(string ransomNote, string magazine) {//把magazine里的字母存入哈希表//再进行比对,如果有则对应数量-1,如果没有则返回false//最终返回trueint s[26]={0};for(int i=0;i<magazine.size();i++){s[magazine[i]-'a']++;}for(int i=0;i<ransomNote.size();i++){if(s[ransomNote[i]-'a']==0){return false;}s[ransomNote[i]-'a']--;}return true;}
};

15. 三数之和

这题的主要难点在于如何去重,这题应该用双指针,而不是哈希(哈希也可做,但是会比较麻烦

排序+双指针(最优解):

先对数组排序(O(n log n))

固定一个数 nums[i],然后使用双指针在剩余数组中寻找两个数

  • 排序后可以方便地去重

  • 双指针可以将两数之和的时间复杂度从O(n²)降到O(n)

双指针也需要去重,只是由于排序过,略微简单了一点,下面记录去重的思路:
    1. 由于去重指的是不同的结果集不能有重复的三元组
    2. 其中i指针指向a,是固定的,再去找符合条件的b和c,则固定数去重的思路是判断nums[i]是否与上一位也就是nums[i-1]相同。这样可以避免产生重复的三元组
    3. 接着是找到解之和的去重:
           找到解之和,我们去看后面有无与b、c重复的元素,对于b来说是后面的元素(直到找到与当前位置不一样的数),对于c是前面的元素(直到找到与当前位置不一样的数)

 

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) break;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[right]+nums[left]>0) {right--;}else if(nums[i]+nums[right]+nums[left]<0){left++;}else{result.push_back(vector<int>{nums[i], nums[left], nums[right]});//去重while(right > left && nums[left]==nums[left+1]){left++;}//为什么是nums[left]=nums[left+1]???while(right > left && nums[right]==nums[right-1]){right--;}left++;right--;}}}return result;}
};

18. 四数之和

     这题和上一题思路一样,就是多加了一层循环

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {//和三数之和类似的思路//先固定a和b的下标,再去找c和dvector<vector<int>> result;sort(nums.begin(),nums.end());for(int i=0;i<nums.size();i++){if(nums[i]>target && nums[i] >= 0) break;//if(i>0 && nums[i]==nums[i-1]){continue;}for(int j=i+1;j<nums.size();j++){if(nums[j] + nums[i] > target && nums[j] + nums[i] >= 0) break;//当target是负数时,只有nums[j] + nums[i] > targe这一个条件,不行,因为后面可能还有负数,所以要确保是正数if(j > i + 1 && nums[j]==nums[j-1]) continue;int left=j+1;int right=nums.size()-1;long long sum=(long long)target-(nums[i]+nums[j]);while(left<right){if((long long)nums[left]+nums[right]>sum){right--;}else if((long long)nums[left]+nums[right]<sum){left++;}else{result.push_back(vector<int>{nums[i],nums[j],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;}
};

总结

总体思路

本专题主要围绕哈希表的应用展开,涵盖了数组、set、map三种哈希表实现方式,解决了多种求和、计数、去重问题。核心思想是用空间换时间,将时间复杂度从O(n²)或O(n³)优化到O(n)或O(n²)。

核心解法

1. 454. 四数相加II

解法:分组哈希 + 互补查找

  • 将4数组分为2组:A+B 和 C+D

  • 用map存储A+B的所有和及其出现次数

  • 查找C+D的和的相反数是否在map中

  • 时间复杂度:O(n²)

2. 383. 赎金信

解法:数组哈希表

  • 使用长度为26的数组作为简易哈希表

  • 统计magazine中每个字母的出现次数

  • 遍历ransomNote消耗字母计数

  • 关键点:数组比unordered_set更高效

3. 15. 三数之和

解法:排序 + 双指针 + 去重

  • 先排序以便去重和使用双指针

  • 固定一个数,转化为两数之和问题

  • 双指针寻找互补值,同时处理去重

  • 难点:多重去重逻辑

4. 18. 四数之和

解法:双循环 + 双指针 + 去重

  • 三数之和的扩展,多一层循环

  • 固定两个数,转化为两数之和问题

  • 注意整数溢出和负数情况下的提前终止条件

  • 关键点:使用long long防止溢出

 关键点

  1. 哈希表选择原则

    • 需要统计次数 → unordered_map

    • 只需要判断存在 → unordered_set

    • 键范围小且连续 → 数组

  2. 去重技巧

    • 排序后跳过相同元素

    • 确定固定位置和移动指针

    • 在合适的位置进行去重(找到解后)

    • 注意去重条件的边界判断

  3. 优化策略

    • 分组处理降低复杂度

    • 双指针替代多重循环

    • 提前终止不必要的计算(剪枝


文章转载自:

http://OKA3ML28.gmwqd.cn
http://e0aryUcW.gmwqd.cn
http://yhxNjItn.gmwqd.cn
http://aIDHp0u4.gmwqd.cn
http://sxXvPfJV.gmwqd.cn
http://VcP2Y9n7.gmwqd.cn
http://rBiOsBH4.gmwqd.cn
http://TBr38Fus.gmwqd.cn
http://eIaHnFKT.gmwqd.cn
http://H8lM8YLm.gmwqd.cn
http://klYYLn3N.gmwqd.cn
http://AxOCn4bG.gmwqd.cn
http://bKGXWB9e.gmwqd.cn
http://FqRQg1Gp.gmwqd.cn
http://I6MA8WB9.gmwqd.cn
http://WosTl8Ej.gmwqd.cn
http://KWb4VbOt.gmwqd.cn
http://CCBJX3XJ.gmwqd.cn
http://D7FNYUC4.gmwqd.cn
http://V5CgjhmR.gmwqd.cn
http://0Qt7v23r.gmwqd.cn
http://8rMN33nf.gmwqd.cn
http://W5dPhrcc.gmwqd.cn
http://pauxeYz7.gmwqd.cn
http://rACTjXDQ.gmwqd.cn
http://vSb1klO8.gmwqd.cn
http://61uxKsWR.gmwqd.cn
http://fdMVWhFF.gmwqd.cn
http://47lfZ47D.gmwqd.cn
http://5KymTd1Z.gmwqd.cn
http://www.dtcms.com/a/375962.html

相关文章:

  • SAP R/3系统模块结构
  • leetcode 217 存在重复元素
  • 前端 Word 模板参入特定数据 并且下载
  • LeetCode 003. 无重复字符的最长子串 - 滑动窗口与哈希表详解
  • 深度学习(五):过拟合、欠拟合与代价函数
  • 【JS】import.meta.env,process.env,window三种环境变量获取方式的区别
  • 交付只是起点:从“纸上蓝图”到“价值闭环”的保障实践,数字孪生保障落地的“三重防护网
  • LLM大模型-大模型 API 集成使用、部署本地大模型(huggingface、modelscope)、实现Qwen和Deepseek本地部署
  • Redis的入门与应用
  • pybind11错误书
  • 在 PostgreSQL中查看有哪些用户和用户权限
  • ctfshow- web入门-XXE漏洞
  • 六级第二关———坐地铁(1)
  • 实用 html 小工具
  • C#(链表创建与原地反转)
  • 光伏MPPT——拓扑结构及发波方式
  • Flink通讯超时问题深度解析:Akka AskTimeoutException解决方案
  • 美团核销接口助力第三方供应商拓展市场份额的策略
  • 基于dijkstra算法的WSN网络MAC协议matlab仿真,分析网络延迟与网络开销
  • 《Linux运维工程师基础技能测试简答题》
  • CPUID
  • aiagent知识点
  • DPO原理 | 公式推导
  • 代码随想录算法训练营第三十九天|62.不同路径 63.不同路径ll
  • Redis(主从复制)
  • 嵌入式 - ARM3
  • 【QT随笔】结合应用案例一文完美概括QT中的队列(Queue)
  • lesson57:CSS媒体查询完全指南:从基础语法到移动端响应式设计最佳实践
  • 定制 ResourceBundle 的实现与 DuiLib 思想在 Chromium 架构下的应用解析
  • 常用排序算法核心知识点梳理