重点:
- leetcode454:要想到分组的思想,将4数变为简单的2数。
- leetcode15:用Collections.sort(triplet);可以实现对list数组的排序。
- leetcode18:方法和15差不多,但需要注意条件判断需要写的简洁明了,k1k2条件超数组范围了。
LeetCode454.四数相加II
/**
* 方法一:分组法把四数相加变成2数相加
* @param nums1
* @param nums2
* @param nums3
* @param nums4
* @return
*/
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
//创建一个hashMap
Map<Integer,Integer> hash = new HashMap<>();
//保存nums1+nums2的所有可能
for(int i=0;i<nums1.length;i++) {
for(int j=0;j<nums2.length;j++) {
hash.put(nums1[i]+nums2[j], hash.getOrDefault(nums1[i]+nums2[j], 0)+1);
}
}
//遍历nums3和nums4的可能
int count=0;
for(int i=0;i<nums3.length;i++) {
for(int j=0;j<nums4.length;j++) {
int key = 0-nums3[i]-nums4[j];
if(hash.containsKey(key)) {
count+=hash.get(key);
}
}
}
return count;
}
LeetCode383. 赎金信
public boolean canConstruct(String ransomNote, String magazine) {
//存储
Map<Character,Integer> hash = new HashMap<>();
for(int i=0;i<magazine.length();i++) {
hash.put(magazine.charAt(i), hash.getOrDefault(magazine.charAt(i), 0)+1);
}
//检查
for(int i=0;i<ransomNote.length();i++) {
int value=hash.getOrDefault(ransomNote.charAt(i), 0);
if(value==0) {
return false;
}
hash.put(ransomNote.charAt(i), value-1);
}
return true;
}
LeetCode15. 三数之和
方法一(暴力法):但当数据量非常大的时候会超时。
public static List<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> s = new HashSet<>();
for (int i = 0; i < nums.length - 2; i++) {
for (int j = i + 1; j < nums.length - 1; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> triplet = Arrays.asList(nums[i], nums[j], nums[k]);
Collections.sort(triplet);
s.add(triplet);
}
}
}
}
return new ArrayList<>(s);
}
方法二(双指针法):固定i,再遍历j,k(两边向中间遍历),当遇到重复数字可跳过(达到去重的效果)。
public static List<List<Integer>> threeSum(int[] nums) {
//创建list结构
List<List<Integer>> s1 = new ArrayList<>();
//先排序,以0为分界点 -4 -1 -1 0 1 2
Arrays.sort(nums);
int i=0;
while (i<=nums.length-3){
int j=i+1,k=nums.length-1;
while (j<k){
//如果出现这种组合的话,加入list中
if(nums[i]+nums[j]+nums[k]==0){
List<Integer> ss = new ArrayList<>();
ss.add(nums[i]);
ss.add(nums[j]);
ss.add(nums[k]);
s1.add(ss);
//去重
do{
j++;
if(j>=k) break;
}while (nums[j-1]==nums[j]);
do{
k--;
if(j>=k) break;
}while (nums[k+1]==nums[k]);
}else if(nums[i]+nums[j]+nums[k]<0){
j++;
}else{
k--;
}
}
//去重
do {
i++;
if(i> nums.length-3){
return s1;
}
}while (nums[i]==nums[i-1]);
}
return s1;
}
LeetCode18.四数之和
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums); // 排序
int n = nums.length;
for (int i = 0; i < n - 3; i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue; // 跳过重复元素
}
for (int j = i + 1; j < n - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue; // 跳过重复元素
}
int k1 = j + 1, k2 = n - 1;
while (k1 < k2) {
long sum = (long) nums[i] + (long) nums[j] + (long) nums[k1] + (long) nums[k2];
if (sum == target) {
list.add(Arrays.asList(nums[i], nums[j], nums[k1], nums[k2]));
while (k1 < k2 && nums[k1] == nums[k1 + 1]) {
k1++;
}
while (k1 < k2 && nums[k2] == nums[k2 - 1]) {
k2--;
}
k1++;
k2--;
} else if (sum < target) {
k1++;
} else {
k2--;
}
}
}
}
return list;
}