454.四数相加II 题解细节去看代码随想录
这个题涉及一个概念——元组,
并且,此题只要求给出满足条件的元组的个数,而不要求求出具体的数,并且不用去重。
这一题一共有四个数组,要想在四个数组中分别找到一个数字满足四个数字之和为零,单纯的四个for循环时间复杂度为n^4,而使用哈希法的map,将四个数组两两为一组,分为a+b和c+d,用key值记录满足(a+b)+(c+d)=0条件的(a+b)和(c+d)是否出现,用value记录出现的次数。最后用count来记录a+b+c+d=0出现的次数,而这里要注意,count=value之和。即
key:a+b的数值,value:a+b数值出现的次数
这里再注意一个点,到c+d遍历循环时,我们要在map中找的是等于0-(c+d)的值,因为a+b+c+d=0,所以0-(c+d)=(a+b),在之前a+b遍历循环时,map储存的是(a+b)的值。
383.赎金信
这道题目和242.有效的字母异位词 (opens new window)很像,242.有效的字母异位词 (opens new window)相当于求 字符串a 和 字符串b 是否可以相互组成 ,而这道题目是求 字符串a能否组成字符串b,而不用管字符串b 能不能组成字符串a。
本题判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成,但是这里需要注意两点。
-
第一点“为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思” 这里说明杂志里面的字母不可重复使用。
-
第二点 “你可以假设两个字符串均只含有小写字母。” 说明只有小写字母,这一点很重
15.三数之和
这道题的重点,去重,详细的去重逻辑建议去看视频解答!
首先将数组排序,然后有一层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相遇为止。
18.四数之和 细节看 代码随想录
四数之和与前面的三数之和思想一样,只不过在三数之和的基础上再多加一个类似三数之和中的i
指针一个for循环,即双指针left和right不变,外加两个for循环。但是这个题的关键在于剪枝和去重。回顾三数之和中的剪枝操作
if (nums[i] > 0) {
return result;
}
如果假设四数之和同样写作
if(nums[i] > target)
就不可行了,因为这是在target为正数的情况下可用的,如果target为负数,这个剪枝就不能用了。
可以写成
if(nums[i] > target && (nums[i] >=0 || target >= 0))
之前的哈希表的经典题目:454.四数相加II (opens new window),相对于本题简单很多,因为本题是要求在一个集合中找出四个数相加等于target,同时四元组不能重复。
而454.四数相加II (opens new window)是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况,所以相对于本题还是简单了不少!