今日学习的文章和视频链接

454文章链接: link
454视频讲解链接: link
383文章链接: link
383视频暂无讲解
15文章链接: link
15视频讲解链接: link
18文章链接: link
18视频讲解链接: link

第454题.四数相加II

看到题目第一想法

题目描述:给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

解题思路:四数相加不用考虑去重,所以想到使用哈希表来处理本题。
我们不仅要记录a + b在集合里出现,还要统计a + b出现过多少次,之后在可以和c + d做一个映射。所以我们不仅要统计是否出现过,还要统计出现过的次数。所以我们选择使用map,用key存是否出现过,value存出现过的次数。

看完代码随想录后的想法

解题步骤:

  1. 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
  2. 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。
  3. 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
  4. 再遍历nums3和nums4数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
  5. 最后返回统计值 count 。

实现过程中遇到的困难

最开始的时候想到了先遍历一个数组,然后再遍历另外三个数组是否在对应集合中出现过。这样再遍历后面三个数组时,时间复杂度为O( n 3 n^3 n3),而先遍历前两个数组,再遍历后两个数组的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

代码

class Solution {public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中for (int a : nums1) {for (int b : nums2) {umap[a + b]++;}}int count = 0; // 统计a+b+c+d = 0 出现的次数// 在遍历nums3和nums4数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。for (int c : nums3) {for (int d : nums4) {if (umap.find(0 - (c + d)) != umap.end()) {count += umap[0 - (c + d)];}}}return count;}
};

383. 赎金信

看到题目第一想法

题目描述:给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

解题思路:发现本题与之前的242.有效的字母异位词相似,只是本题是求 字符串a能否组成字符串b,而不用管字符串b 能不能组成字符串a

看完代码随想录后的想法

判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成时需注意两点:

  • 第一点“magazine 中的每个字符只能在 ransomNote 中使用一次”
  • 第二点ransomNote 和 magazine 由小写英文字母组成

因为本题目只有小写字母,所以采用一个长度为26的数组来记录magazine里字母出现的次数。

再用ransomNote去验证这个数组是否包含ransomNote所需的所有字母。

使用哈希法来解决本题。

实现过程中遇到的困难

本想着使用map,但是感觉有点大材小用,看了代码随想录了解到在本题的情况下,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!

代码

class Solution {public:bool isAnagram(string s, string t) {int record[26]={0};for(int i = 0;i < s.size();i++){record[s[i] - 'a']++;}for(int i = 0;i < t.size();i++){record[t[i] - 'a']--;}for(int i = 0;i < 26;i++){if(record[i] != 0){return false;}}return true;}
};

第15题. 三数之和

看到题目第一想法

题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意: 答案中不可以包含重复的三元组。

解题思路:依然想着使用哈希法去解决本问题,但题目中要求我们去重,但是对去重的部分思路不是很清晰。

看完代码随想录后的想法

随想录中给了哈希法双指针法两种解法。

哈希法

先使用两层for循环确定a + b,然后使用哈希法来确定 0-(a+b) 是否在 数组里出现过。

但要把符合条件的三元组放进vector中,然后再去重,这样是非常费时的,很容易超时。

时间复杂度可以做到O(n^2),但还是比较费时的,因为不好做剪枝操作

双指针法

双指针法要比哈希法高效,我们看如下动画:

首先将数组排序,然后有一层for循环,i从下标0的地方开始,同时将一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上。

依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i],b = nums[left],c = nums[right]。

移动left 和right:

  • 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。
  • 如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些。

直到left与right相遇为止。

实现过程中遇到的困难

去重的操作还不是很熟悉

去重逻辑思考

其实主要考虑三个数的去重。 a, b ,c, 对应的就是 nums[i],nums[left],nums[right]

a的去重

a 如果重复了怎么办,a是nums里遍历的元素,那么应该直接跳过去。

但是是判断 nums[i] 与 nums[i + 1]是否相同,还是判断 nums[i] 与 nums[i-1] 是否相同?都是和 nums[i]进行比较,是比较它的前一个,还是比较他的后一个?

如果我们比较它的后一个:

if (nums[i] == nums[i + 1]) { // 去重操作continue;
}

那就我们就把 三元组中出现重复元素的情况直接pass掉了。 例如{-1, -1 ,2} 这组数据,当遍历到第一个-1 的时候,判断 下一个也是-1,那这组数据就pass了。

但要记住我们是不能有重复的三元组,但三元组内的元素是可以重复的!

此时这里是有两个重复的维度。

所以应该比较它的前一个:

if (i > 0 && nums[i] == nums[i - 1]) {continue;
}

这么写就是当前使用 nums[i],我们判断前一位是不是一样的元素,在看 {-1, -1 ,2} 这组数据,当遍历到 第一个 -1 的时候,只要前一位没有-1,那么 {-1, -1 ,2} 这组数据一样可以收录到 结果集里。

b与c的去重

当去重的逻辑中加入

代码

class Solution {public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_set<int> result_set;unordered_set<int> nums_set(nums1.begin(),nums1.end());for(int num : nums2){if(nums_set.find(num) != nums_set.end()){result_set.insert(num);}}return vector<int>(result_set.begin(),result_set.end());}
};

第202题. 快乐数

看到题目第一想法

题目描述:

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。

如果 n 是快乐数就返回 True ;不是,则返回 False 。

有如下想法:

关键:** 若无限循环,那么求和的过程中,sum会重复出现**

所以采用哈希法来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。

判断sum是否重复出现就可以使用unordered_set

看完代码随想录后的想法

思路相同

实现过程中遇到的困难

对取数值各个位上的单数操作不是很熟悉

代码

class Solution {public:// 取数值各个位上的单数之和int getSum(int n) {int sum = 0;while (n) {sum += (n % 10) * (n % 10);n /= 10;}return sum;}bool isHappy(int n) {unordered_set<int> set;while(1) {int sum = getSum(n);if (sum == 1) {return true;}// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return falseif (set.find(sum) != set.end()) {return false;} else {set.insert(sum);}n = sum;}}
};

1. 两数之和

看到题目第一想法

题目描述:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

本题解决有困难,对map不是很了解。

看完代码随想录后的想法

本题需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。

本题我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素value来存下标,那么使用map正合适。

为何使用之前用过的set呢?

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。

而map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。

在map在C++的3种类型中,选择std::unordered_map,因为这道题目中并不需要key有序,选择std::unordered_map 效率更高

使用map需注意如下两点:

  • map用来做什么
  • map中key和value分别表示什么

关于第一点,map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

关于第二点,这道题我们需要给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。

判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。

所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素比配的数值,如果有,就是找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

实现过程如下图:

实现过程中遇到的困难

对取数值各个位上的单数操作不是很熟悉

代码


今日收获

1.对哈希表的基础理论有所了解

2.知道了set和map的应用场景

3.使用模板库还是不太熟练,后续需要加强

今日学习时长3h

该文章图片均来自Carl哥的代码随想录,在此特别感谢

代码随想录算法训练营第七天|454.四数相加II、383. 赎金信、15. 三数之和、18. 四数之和相关推荐

  1. 代码随想录算法训练营day6| 454.四数相加II 383.赎金信 15.三数之和 18.四数之和

    代码随想录算法训练营day6| 454.四数相加II 383.赎金信 15.三数之和 18.四数之和 LeetCode 454 四数相加II 题目链接: 454.四数相加II class Soluti ...

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

    一.454.四数相加II 力扣 思路:第一眼还没反应过来,真是缺练.在四个数组中分别寻找,可以先把前两个数组的和先存入map中,再计算后两个数组元素的和,看一下相反数在map中出现没有,出现过就res ...

  3. 代码随想录算法训练营第6天 | 454. 四数相加 II 383. 赎金信 15. 三数之和 18. 四数之和

    一.Leetcode 454. 四数相加 II 相当于两数相加.但是呢很巧妙的是,卡哥在遍历CD数组时把查哈希表的方法融入了进去.学习一下. 二.Leetcode 383. 赎金信 更简单了,主要是审 ...

  4. 代码随想录算法训练营第七天 | 454. 四数相加 II、383. 赎金信、15. 三数之和、18. 四数之和

    454. 四数相加 II 题解及想法 通过两个for循环先遍历a和b,key放a和b两数之和,value 放a和b两数之和出现的次数,再通过两个for循环遍历c和d,如果0-(c+d) 在map中出现 ...

  5. 代码随想录算法训练营第七天| 454.四数相加II,383. 赎金信,15. 三数之和,18. 四数之和

    Leetcode 454.四数相加II 思路分析: 本题直观的想法是采取暴力法,四数相加就用四层for循环.虽然能得到结果,但时间复杂度为o(n4),当数组长度较大时,Leetcode便提示超时.该方 ...

  6. 代码随想录算法训练营第七天|454、四数相加Ⅱ 383、赎金信15、三数之和18、四数之和

    454.四数相加Ⅱ.383.赎金信.15.三数之和四数之和 四数相加 对于四数相加,我们可以定义一个map用来记录nums1与nums2的和对应次数,再遍历nums3与nums4,如果存在c与d使得a ...

  7. 代码随想录算法训练营第七天| 454.四数相加II 、383. 赎金信 、15. 三数之和 、18. 四数之和 。

    454.四数相加II 题目链接 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i ...

  8. 代码随想录算法训练营第七天| 454.四数相加II 、383. 赎金信、15. 三数之和、18. 四数之和

    454. 四数相加 II 题目: 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= ...

  9. 代码随想录算法训练营第七天 | 454.四数相加II ,383. 赎金信 ,15. 三数之和,18. 四数之和

    一.参考资料 四数相加II 题目链接/文章讲解/视频讲解:https://programmercarl.com/0454.%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0II. ...

最新文章

  1. kepserver 三菱fx_#电工培训# #plc培训# PLC培训 学在智通 赢在职场【三菱plc吧】
  2. stm32f4 RAM中运行程序 读保护设置
  3. gitlab 开源项目 星_49必须了解的机器学习开源项目,Github上平均3600星
  4. nginx之rtmp模块引用计数设计
  5. fasttext的基本使用 java 、python为例子
  6. 7-37 模拟EXCEL排序 (25 分)(思路+详解+超时解决 兄弟们冲呀呀呀呀呀呀)
  7. 简要描述内部连接和外部连接之间的区别_sqlserver的几种常见连接方法
  8. emlog简洁大气白色风格资源站模板源码
  9. python把csv做成柱状图_用Python的Matplotlib模块实现CSV数据格式的可视化
  10. 20200721每日一句
  11. 2021-08-31Flink 中的核心概念和基础考察
  12. Eprime与EEG的接口
  13. ssci源刊里有开源期刊吗_SSCI和SCI期刊投稿指南-以经济学和管理学为例
  14. win10开机就卡死在桌面上怎么解决
  15. sublime text 提示error while loading pyvb binvry:exit code3 try tomanually install pyvb的处理方法
  16. CSS基础 | (1) CSS是什么
  17. Composer修改镜像源
  18. Android学习记录
  19. android 装饰着模式,Android与设计模式——装饰者(Decorator)模式
  20. 上海市计算机学会-买二送一

热门文章

  1. 关于计算机的英语手抄报简单,简单漂亮的英语手抄报图片大全
  2. jQuery常用方法汇总
  3. win10 64位安装绿色版mysql-5.7.16-winx64
  4. 如何测试服务器及端口是否畅通
  5. SEEDLAB2.0-Spectre Attack Lab
  6. npm install安装报错 gyp info it worked if it ends with ok
  7. 专家称我国带薪休假制度偏重单位利益-长假-黄金周-带薪休假
  8. HTML中的position属性
  9. event对象的一些方法(取消冒泡,阻止默认行为)
  10. Ubuntu下Pycharm切换中文输入法无法输入中文解决方法