代码随想录训练营 Day07 - 哈希表(下)
作者:jjn0703
- 2023-07-04 江苏
本文字数:3121 字
阅读完需:约 10 分钟
作业题
454. 四数相加 II
package jjn.carl.hashtable;
import java.util.HashMap;
import java.util.Map;
/**
* @author Jiang Jining
* @since 2023-07-04 21:33
*/
public class LeetCode454 {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer, Integer> map = new HashMap<>();
int res = 0;
for (int first : nums1) {
for (int second : nums2) {
map.put(first + second, map.getOrDefault(first + second, 0) + 1);
}
}
for (int third : nums3) {
for (int fourth : nums4) {
res += map.getOrDefault(-third - fourth, 0);
}
}
return res;
}
public static void main(String[] args) {
int[] nums1 = new int[]{1, 2};
int[] nums2 = new int[]{-2, -1};
int[] nums3 = new int[]{-1, 2};
int[] nums4 = new int[]{0, 2};
int fourSumCount = new LeetCode454().fourSumCount(nums1, nums2, nums3, nums4);
System.out.println("fourSumCount = " + fourSumCount);
}
}
复制代码
383. 赎金信
package jjn.carl.hashtable;
/**
* @author Jiang Jining
* @since 2023-07-04 21:45
*/
public class LeetCode383 {
public boolean canConstruct(String ransomNote, String magazine) {
int[] charCount = new int[26];
for (char c : ransomNote.toCharArray()) {
charCount[c - 'a']++;
}
for (char c : magazine.toCharArray()) {
charCount[c - 'a']--;
}
for (int j : charCount) {
if (j > 0) {
return false;
}
}
return true;
}
public static void main(String[] args) {
String ransomNote = "aa", magazine = "aab";
boolean canConstruct = new LeetCode383().canConstruct(ransomNote, magazine);
System.out.println("canConstruct = " + canConstruct);
}
}
复制代码
15. 三数之和
package jjn.carl.hashtable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Jiang Jining
* @since 2023-07-04 22:13
*/
public class LeetCode15 {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (nums[i] > 0) {
return result;
}
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1, right = nums.length - 1;
while (left < right) {
if (nums[left] + nums[right] + nums[i] < 0) {
left++;
} else if (nums[left] + nums[right] + nums[i] > 0) {
right--;
} else {
result.add(List.of(nums[i], nums[left], nums[right]));
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
left++;
right--;
}
}
}
return result;
}
public static void main(String[] args) {
int[] nums = new int[]{-1, 0, 1, 2, -1, -4};
List<List<Integer>> threeSum = new LeetCode15().threeSum(nums);
System.out.println("Arrays.toString(threeSum) = " + threeSum.toString());
}
}
复制代码
18. 四数之和
package jjn.carl.hashtable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Jiang Jining
* @since 2023-07-04 23:10
*/
public class LeetCode18 {
public List<List<Integer>> fourSum(int[] nums, int target) {
// 排序很关键,是双指针法的前提
Arrays.sort(nums);
long res = 0L;
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 3; i++) {
// target 可以为负数,负数相加会变得更小
if (nums[i] > 0 && nums[i] > target && target >= 0) {
return result;
}
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.length; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
int left = j + 1, right = nums.length - 1;
while (left < right) {
// 防止加法越界
long cur = (long) nums[i] + (long) nums[j] + (long) nums[left] + (long) nums[right];
if (cur < target) {
left++;
} else if (cur > target) {
right--;
} else {
result.add(List.of(nums[i], nums[j], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
}
}
}
}
return result;
}
public static void main(String[] args) {
int[] nums = new int[]{1, 0, -1, 0, -2, 2};
int target = 0;
List<List<Integer>> fourSum = new LeetCode18().fourSum(nums, target);
System.out.println("fourSum = " + fourSum);
// Case two
nums = new int[]{2, 2, 2, 2, 2, 2};
target = 8;
fourSum = new LeetCode18().fourSum(nums, target);
System.out.println("fourSum = " + fourSum);
// 非常猥琐的测试用例
nums = new int[]{1000000000, 1000000000, 1000000000, 1000000000};
target = -294967296;
fourSum = new LeetCode18().fourSum(nums, target);
System.out.println("fourSum = " + fourSum);
}
}
复制代码
总结
某些场景用数组非常合适,如只会有小写的字母等,采用哈希表速度可能不如数组快;输入的数据可能性没有限制,则只能用哈希表;
N 数之和,基本思路:确定左边的数,留下最后两个,用双指针不断收缩,求解答案,难点在于去重。
划线
评论
复制
发布于: 刚刚阅读数: 4
版权声明: 本文为 InfoQ 作者【jjn0703】的原创文章。
原文链接:【http://xie.infoq.cn/article/6d55f0c03d817e996fcb03c72】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
jjn0703
关注
Java工程师/终身学习者 2018-03-26 加入
USTC硕士/健身健美爱好者/Java工程师.
评论