1.题目链接:LeetCode454四数相加
题目描述:
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
解法:
①此题要解决的是四元组的值相加等于0,可以分析得到,遍历前两个数组,将元素和,和该元素和出现的次数放到map中。
②然后遍历后两个数组,求0-后两个数组的元素和并在map中找,如果有:count+=value。
③最后return count即可。
下面为代码(java):
2.题目链接:LeetCode383赎金信
题目描述:
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
解法:
①其实和求有效的字母异位词那道题基本一样,此题也是将ransomNote放入一个哈希数组中,并记录每个字符出现的次数。
②然后遍历magazine,将哈希数组中对应的次数进行--。
③最后遍历哈希数组,如果数组中出现>0的元素,就返回false。若没有出现,就返回true。
④注意在最开始的时候要讨论特殊情况以减少计算。即若ransomNote.length() > magazine.length(),就直接返回false。
下面为代码(java):
3.题目链接:LeetCode15三数之和
题目描述:
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
解法:
①定义三个位置,i,left,right。left = i+1,right = nums.length-1。即本题使用双指针解法。首先要对数组进行排序,因为在排序后可以方便我们进行剪枝和双指针操作。
②要注意的是此题要的是不包含重复的三元组,所以要对nums[i],nums[left],nums[right]进行去重。去重操作:对于i,nums[i-1] == nums[i] && i > 0。因为,如果nums[i] == nums[i+1],相当于在得③到的四元组中,比较i和left,但是此题中只是要不能有重复的三元组,但是nums[i]和nums[left]是可以相等的。所以不能这样操作。
④对于left 和 right ,如果nums[left] == nums[left+1] left++;如果nums[right] == nums[right-1],right--。
同时要注意的是,要在获取到一个完整的三元组后再对left和right去重。如果先对其进行去重再获得元组的话,会少获得元组值,可以举例知道。
⑤注意在双指针移动的时候,是right>left为循环条件,因为如果left == right的时候,相当于两个指针移动到了同一个位置,这样我们相当于少取了一个元素,所以要 right>left。
⑥此题中涉及了 一些操作要知道什么意思,创建一个列表其中的内容是列表,而列表中的内容为整数。将数组元素排序,Array.sort(数组名),将四个元素作为列表返回 :reuslt.add(Arrays.asList(nums[i] , nums[left] , nums[right])。
下面为代码(java):
4.题目链接:LeetCode18四数之和
题目描述:
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
解法:
①此题和15三数之和差不多,其实就是多了一个新位置k。同样要对位置k进行剪枝和去重。
②注意剪枝的时候,因为此题中的target可能为负数也可能为正数,故要满足nums[k] > 0 && nums[k] > target的时候,才能进行剪枝。这个和15不同。
③而对于i位置,也要进行剪枝和去重,剪枝条件就是 nums[k] > 0&& nums[k] +nums[i] > target。去重原理一样。
④下面的双指针移动和双指针位置去重以及返回四元组值过程是一样的。
⑤还有本题要注意的是sum可能超出int的范围,要给他强转成long型。
下面为代码(java):
5.总结:
①今天是哈希表的深度应用,第一题四数相加,其实还是将其分为两两一组,将一组的和和次数放到map中,然后遍历另两个数组,求0 -(两数之和),看在map中存在吗?如果存在,此时count+=value就是多少个。其实和两数之和的解法非常像,都是将,某些元素存到map中,再遍历另外的数组,然后0-xx是否在map中出现,若出现了返回对应的下标。
②第二题和昨天的是否是有效的字母异位词,都是将一个数组或者字符串放到一个哈希数组中,然后通过++,--操作来进行值对应哈希数组中值的变化,最后通过值和0的关系来判断是否满足条件。
③第三第四题和前两题的不同就是,要去重,用哈希法比较麻烦,所以用了双指针思想进行去重。几个数之和==?就有几个位置,后两个位置为双指针的位置,左指针指向i+1,右指针指向数组末。
④对于前面的位置还要进行剪枝操作。注意两题剪枝条件的不同。而对于去重操作,要注意nums[i] == nums[i-1]和nums[i] == nums[i+1]的区别。
⑤在今天手撕代码的时候,有continue那行总报错,因为continue要在循环中才能操作,要注意}的位置,不能搞错了。