四数相加,又是加加加一类的哈哈,与之前三数之和四数之和不同,这道题没有要求不能重复,也就是说我们不用对他们进行排序了
思路:一开始想的是三次遍历加哈希值运算,然后看了题解里的一句话
也就是说x个数相加的题目,只要不要求有序,那么我们就可以把他们分为两组,使用map容器,key放相加之后的值,value放出现的次数,然后在第二个map里面寻找key = -key1就好,这是时间复杂度最低的做法
那么为什么是一半左右呢,我们简单举个例子就能解释,例如一共四组,那么加入 1-3分,那么其中一组map的生成的时间复杂度就是n的的三次方,最终的时间复杂度也是n 的三次方,而如果对半分,就只有n平方了,降了一个数量级,所以对半分是为了遍历生成map 的时候尽可能低的数量级。
可以做的优化:
在生成第二组map 的时候一边生成,一边判断key是否等于前面key 的负数
总结:对于 A+B+...+N = 0 的题目,首先判断结果是否要求无重复
无重复:那就要对数组进行排序,之后使用双指针加for循环遍历,同时要注意是否重复的问题
有重复:那么就将所有数组对半分,用两个map容器去承载,之后比较后一个map的key是否是前一个key 的负数即可
贴上通过代码(java)
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
//使用hashMap存下前两组和后两组的和
Map<Integer,Integer> a1 = toMap(nums1,nums2);
Map<Integer,Integer> a2 = toMap(nums3,nums4);
int total = 0;
//遍历第二个map,直接用哈希运算寻找key=-key1
for (Map.Entry<Integer, Integer> integerIntegerEntry : a1.entrySet())
{
int sum = integerIntegerEntry.getKey();
if (a2.containsKey(-sum))
total += a2.get(-sum)*integerIntegerEntry.getValue();
}
return total;
}
private Map<Integer,Integer> toMap(int[] nums1, int[] nums2)
{
//创建结果集
Map<Integer,Integer> a1 = new HashMap<>();
//遍历前两组
for(int i = 0;i < nums1.length;i++)
{
for(int j = 0;j < nums2.length;j++)
{
//先判断两数之和是否存在
if (a1.containsKey(nums1[i] + nums2[j]))
{
a1.put(nums1[i] + nums2[j],a1.get(nums1[i] + nums2[j]) + 1);
}else
{
//不存在
a1.put(nums1[i] + nums2[j],1);
}
}
}
return a1;
}
}