1、454.四数相加 II
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int res=0;
//key:a+b的数值,value:a+b数值出现的次数
Map<Integer, Integer> map = new HashMap<Integer,Integer>();
// 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中
for(int i:nums1){
for(int j:nums2){
int sum=i+j;
//key:两元素之和 value:出现次数
map.put(sum,map.getOrDefault(sum,0)+1);
}
}
// 统计a+b+c+d = 0 出现的次数
int count =0;
for(int i:nums3){
for(int j:nums4){
//key:两元素之和 value:出现次数
res+=map.getOrDefault(0-i-j,0);
}
}
return res;
}
}
getOrDefault()该方法接受两个参数:要查找的键和默认值。如果键存在,则返回与该键关联的值,否则返回指定的默认值。
2、383.赎金信
用数组实现哈希解法
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
// 剪枝shortcut
if (ransomNote.length() > magazine.length()) {
return false;
}
int[] record = new int[26];
for (char c : magazine.toCharArray()) {
record[c - 'a']++;
}
for (char c : ransomNote.toCharArray()) {
record[c - 'a']--;
}
//如果数组中存在负数,说明ransomNote中存在magzine中没有的字符
for (int i : record) {
if (i < 0) {
return false;
}
}
return true;
}
}
3、15.三数之和
两数之和 就不能使用双指针法,因为两数之和要求返回的是索引下标, 而双指针法一定要排序,一旦排序之后原数组的索引就被改变了。
如果两数之和要求返回的是数值的话,就可以使用双指针法了。
去重逻辑有待回顾。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
// 找出a + b + c = 0
// a = nums[i], b = nums[left], c = nums[right]
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
return result;
}
if (i > 0 && nums[i - 1] == nums[i]) {// 去重a
continue;
}
int left = i + 1;
int right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum > 0) {
right--;
} else if (sum < 0) {
left++;
} else {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
// 去重逻辑放在找到的第一个三元组后,对 b,c 去重
while (left < right && nums[left] == nums[left + 1])
left++;
while (left < right && nums[right - 1] == nums[right])
right--;
left++;
right--;
}
}
}
return result;
}
}
4、18.四数之和
四数之和,和三数之和是一个思路,都是使用双指针法, 基本解法就是在三数之和的基础上再套一层for循环。
即固定住 i, j 位置的值,左右指针去后边区间找两头的值。
去重部分有待回顾
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
// 剪枝操作
if (nums[i] > 0 && nums[i] > target) {
return result;
}
// 对nums[i]去重
if (i > 0 && nums[i - 1] == nums[i]) {
continue;
}
for (int j = i + 1; j < nums.length; j++) {
if (j > i + 1 && nums[j - 1] == nums[j]) {
continue;
}
int left = j + 1;
int right = nums.length - 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 {
result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
//对nums[left]和nums[right]去重
while (left < right && nums[right - 1] == nums[right])
right--;
while (left < right && nums[left] == nums[left + 1])
left++;
left++;
right--;
}
}
}
}
return result;
}
}