代码随想录day07
454.四数相加II
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int count = 0;
Map<Integer , Integer> map = new HashMap();
//将nums1和nums2的和放入map中,值作key,值出现的次数做value
for(int i : nums1){
for(int j : nums2){
int sum = i + j;
map.put(sum,map.getOrDefault(sum,0) + 1);
}
}
//将nums3与nums4的和与map进行匹配
//每有一个符合条件的令count+1
for(int i : nums3){
for(int j : nums4){
count += map.getOrDefault(0-i-j,0);
}
}
return count;
}
}
383.赎金信
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
//ransomNote的长度必须小于magazine
if(ransomNote.length() > magazine.length()){
return false;
}
//定义一个字母数组,数组的值代表每个字母出现的次数
int[] num = new int[26];
//遍历ransomNote数组,其中每出现的每个字母-1
for(char c : ransomNote.toCharArray()){
num[c - 'a'] -= 1;
}
//遍历magazine数组,其中每出现的每个字母+1
for(char c: magazine.toCharArray()){
num[c - 'a'] += 1;
}
//num有负数说明不符合条件
for(int i : num){
if(i < 0){
return false;
}
}
return true;
}
}
15.三数之和
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
// n 为 3,从 nums[0] 开始计算和为 0 的三元组
return nSumTarget(nums, 3, 0, 0);
}
// n 填写想求的是几数之和,start 从哪个索引开始计算(一般填 0),target 填想凑出的目标和
public List<List<Integer>> nSumTarget(
int[] nums, int n, int start, int target) {
int sz = nums.length;
List<List<Integer>> res = new ArrayList<>();
// 至少是 2Sum,且数组大小不应该小于 n
if (n < 2 || sz < n) return res;
// 2Sum 是 base case
if (n == 2) {
// 双指针那一套操作
int lo = start, hi = sz - 1;
while (lo < hi) {
int sum = nums[lo] + nums[hi];
int left = nums[lo], right = nums[hi];
if (sum < target) {
while (lo < hi && nums[lo] == left) lo++;
} else if (sum > target) {
while (lo < hi && nums[hi] == right) hi--;
} else {
List<Integer> triplet = new ArrayList<>();
triplet.add(left);
triplet.add(right);
res.add(triplet);
while (lo < hi && nums[lo] == left) lo++;
while (lo < hi && nums[hi] == right) hi--;
}
}
} else {
// n > 2 时,递归计算 (n-1)Sum 的结果
for (int i = start; i < sz; i++) {
List<List<Integer>> sub =
nSumTarget(nums, n - 1, i + 1, target - nums[i]);
for (List<Integer> arr : sub) {
// (n-1)Sum 加上 nums[i] 就是 nSum
arr.add(nums[i]);
res.add(arr);
}
while (i < sz - 1 && nums[i] == nums[i + 1]) i++;
}
}
return res;
}
}
18.四数之和
参考了灵茶山艾府大佬的解法
仿照三数之和的做法有一组,过不去
nums =[1000000000,1000000000,1000000000,1000000000]
target =-294967296
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
int n = nums.length;
for (int a = 0; a < n - 3; a++) { // 枚举第一个数
long x = nums[a]; // 使用 long 避免溢出
if (a > 0 && x == nums[a - 1]) continue; // 跳过重复数字
if (x + nums[a + 1] + nums[a + 2] + nums[a + 3] > target) break; // 优化一
if (x + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue; // 优化二
for (int b = a + 1; b < n - 2; b++) { // 枚举第二个数
long y = nums[b];
if (b > a + 1 && y == nums[b - 1]) continue; // 跳过重复数字
if (x + y + nums[b + 1] + nums[b + 2] > target) break;
if (x + y + nums[n - 2] + nums[n - 1] < target) continue;
int c = b + 1, d = n - 1;
while (c < d) { // 双指针枚举第三个数和第四个数
long s = x + y + nums[c] + nums[d]; // 四数之和
if (s > target) d--;
else if (s < target) c++;
else { // s == target
ans.add(List.of((int) x, (int) y, nums[c], nums[d]));
for (c++; c < d && nums[c] == nums[c - 1]; c++) ;
for (d--; d > c && nums[d] == nums[d + 1]; d--) ;
}
}
}
}
return ans;
}
}