一、前言
在此先向各位uu说声抱歉,端午节本来只打算休息一天的,结果由于某些原因中间又耽误了两天,今天才重新开始了学习、刷题,向uu们说声抱歉。那么就说说今天的题目吧,今天的题目不算是很难,即不使用map等hash表也可以做出来,只是要超时,具体的放到下面来说吧,
二、题目(力扣第454题—四数相加||. - 力扣(LeetCode))
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
示例一:
输入:
- A = [ 1, 2]
- B = [-2,-1]
- C = [-1, 2]
- D = [ 0, 2]
输出:
2
解释:
两个元组如下:
- (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
- (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
三、题解
这个题看着是从四个数组选择不同元素组成相加等于0即可,因此最简单的暴力解法就是四重循环(简单、粗暴)但是会超时,因为时间复杂度实在是太大了(O())力扣这里会报超时的,因此这个办法在此处不行,因此这里需要使用到map,因为这道题目是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况,然后将四个数组分成两个部分,前两个数组一部分,后两个数组一部分,两者想加等于0即可。话不多说,上代码具体来讲讲。(对了卡哥的讲解也放在这里了代码随想录)
代码:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
int co=0;//存储有多少个
unordered_map<int,int> unmap;
for(auto a:nums1){//遍历循环nums1、nums2两个数组
for(auto b:nums2){
unmap[a+b]++;
}
}
for(auto c:nums3){
for(auto d:nums4){
if(unmap.find(0-(c+d))!=unmap.end()){
co+=unmap[0-(c+d)];
}
}
}
return co;
}
接下来就具体讲讲代码部分
定义的map的key(类似于数组下标)来存放两个数组的元素相加的值,而map中的value(类似于数组下标代表的值)来存放两个元素相加的值出现的次数。
这里的循环是c++11里面比较常见的循环方式,以前也讲过,大家可以尝试用这个来替代以前的for循环(因为这种循环是使用迭代器实现的,对于set、map这种不能使用下标的都是可以来“遍历”其中的元素的)
for(auto a:nums1)
使用a和b来遍历nums1和nums2中的元素,用map的key来存放a、b和,map的value来存放a、b和的值出现的次数。
for(auto a:nums1){//遍历循环nums1、nums2两个数组
for(auto b:nums2){
unmap[a+b]++;//map中的key来存放a+b的值,map中的value来存放a+b出现的次数
}
}
这里的c和d就是后面两个数组nums3、nums4的遍历变量(与a和b的作用一样),主要讲讲下面两行代码的含义。使用find函数可以简便的搜索map中是否有该元素存在,这里的0-(c+d)就等于a+b的值(因为a+b+c+d=0,将四个数组分成两部分,a+b一部分先存入map中,c+d一部分用来检查map中是否有a+b这个值的元素存在,((0-c+d)来检查))。若存在该元素,则将该元素对应出现的次数加到co上即可。
if(unmap.find(0-(c+d))!=unmap.end())
co+=unmap[0-(c+d)];
四、后记
find函数在map、set中是非常好用的,来检查是否存在该元素。大家要多多尝试使用。然后就是遍历的形式for(auto it:nums)这种遍历对任何数据结构都是适用的,希望大家也都适用这种遍历形式。最后希望大家多多练习,不要像我三天打鱼两天晒网(我错了www)。各位加油加油,我们都有光明的未来!