这题经典而且不简单。Map对应的是前两个数组的各个元素两数之和以后需要的另两个数组的和map该和出现的次数。
后面再求另外两个数组的和时,只需要看map里是否有,有多少”需要“的和元素,并加其所有的可能性即可。
class Solution {
Map<Integer, Integer> map = new HashMap<>();
private void findSum(int[] nums1, int[] nums2){
int len1 = nums1.length;
int len2 = nums2.length;
for(int i = 0; i < len1; ++i){
for(int j = 0; j < len2; ++j){
int sum = -nums1[i] - nums2[j];
map.merge(sum, 1, Integer::sum); //意思:如果不存在sum,建立sum map到1;如果已经存在sum,++当前sum。
}
}
}
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int count = 0;
int len1 = nums3.length;
int len2 = nums4.length;
findSum(nums1, nums2);
for(int i = 0; i < len1; ++i){
for(int j = 0; j < len2; ++j){
int sum = nums3[i] + nums4[j];
if(map.containsKey(sum)){
count += map.get(sum);
}
}
}
return count;
}
}
2.Ransom Note
简单题
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr = new int[26];
int len = magazine.length();
int len2 = ransomNote.length();
for(int i = 0; i < len; ++i){
++arr[magazine.charAt(i) - 'a'];
}
for(int i = 0; i < len2; ++i){
int idx = ransomNote.charAt(i) - 'a';
--arr[idx];
if(arr[idx] < 0) return false;
}
return true;
}
}
双指针做法,没有剪枝,也懒得优化了。正确答案和这个应该大差不离。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
int len = nums.length;
for(int i = 0; i < len-2; ++i){
int left = i+1, right = len-1;
while(left < right){
while(left < right && nums[left] + nums[right] + nums[i] > 0) --right;
while(left < right && nums[left] + nums[right] + nums[i] < 0) ++left;
if(left < right && nums[left] + nums[right] + nums[i] == 0){
List<Integer> tmp = new ArrayList<>();
tmp.add(nums[left]); tmp.add(nums[right]); tmp.add(nums[i]); res.add(tmp);
while(left < right && nums[right] == nums[right-1]) {
--right;
continue;
}
--right;
continue;
}
}
while(i < len-2 && nums[i] == nums[i+1]) ++i;
}
return res;
}
}
-
4Sum
这题是真的难写啊…很多edge cases要考虑,并且我借鉴了代码随想录《三数之和》 的写法。整体不难,但很折磨人。class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { Arrays.sort(nums); List<List<Integer>> res = new ArrayList<>(); int len = nums.length; for(int i = 0; i < len-3; ++i){ while(i > 0 && i < len-3 && nums[i] == nums[i-1]) ++i; for(int j = i+1; j < len-2; ++j){ while(j < len-2 && i != j-1 && nums[j] == nums[j-1]) ++j; int left = j+1, right = len-1; while(left < right){ long sum = (long) nums[i] + nums[j] + nums[left] + nums[right]; if(sum > target){ --right; }else if(sum < target){ ++left; }else{ res.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right])); while(left < right && nums[left+1] == nums[left]) {++left;} while(left < right && nums[right] == nums[right-1]) {--right;} ++left; --right; } } } } return res; } }
文章详细介绍了使用Java解决四类经典的算法问题:四SumII通过构建哈希表来计算两数组元素和的出现次数,RansomNote判断ransomNote是否能由magazine中的字符组成,3Sum和4Sum采用双指针法找到数组中和为目标值的所有三元组和四元组。

被折叠的 条评论
为什么被折叠?



