day07 打卡454. 四数相加 II 383. 赎金信 15. 三数之和 18. 四数之和

day07 打卡454. 四数相加 II 383. 赎金信 15. 三数之和 18. 四数之和

454. 四数相加 II

454题目链接

1.看了视频讲解后写的。使用map,记住nums1和nums2的相加,再到nums3和nums4中寻找相加等于0的组合。

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        if (nums1 == null || nums1.length == 0) {
            return 0;
        }
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0 ; i<nums1.length ; i++) {
            for (int j = 0 ; j<nums2.length ; j++) {
                int sum = nums1[i] + nums2[j];
                if (map.containsKey(sum)) {
                    Integer count = map.get(sum);
                    map.put(sum, count+1);
                } else {
                    map.put(sum, 1);
                }
            }
        }
        int result = 0;

        for (int i = 0 ; i<nums3.length ; i++) {
            for (int j = 0 ; j<nums4.length ; j++) {
                int sum = 0 - nums3[i] - nums4[j];
                if (map.containsKey(sum)) {
                    Integer count = map.get(sum);
                    result += count;
                }
            }
        }
        return result;
    }
}

383. 赎金信

383题目链接

1.这道题目跟昨天的有效的字母异位词是一样的思路,记住不同字母对应的次数。再次循环减去次数,如果次数不足,就返回false。

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        boolean result = true;
        int[] record = new int[26];

        for (int i = 0 ; i<magazine.length() ; i++) {
            char c = magazine.charAt(i);
            record[c - 'a']++;
        }

        for (int i = 0 ; i<ransomNote.length() ; i++) {
            char c = ransomNote.charAt(i);
            if (record[c - 'a'] <= 0) {
                result = false;
                break;
            } else {
                record[c - 'a']--;
            }
        }
        return result;
    }
}

15. 三数之和

15题目链接

1.超出时间限制。思路:循环两次,使用map,key为两次相加,value记住i与j。再循环一次,找到相加为0的k,判断i、j、k是否都不想等,再调用existSameList判断result中是否已经有相同的list了,如果没有,加入result中。

但是当nums数量很多的时候,existSameList消耗太多时间了,每一次都要全部便利再是否一致。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>(); 
        Map<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0 ; i<nums.length-1 ; i++) {
            for (int j = i+1; j<nums.length ; j++) {
                int sum = nums[i] + nums[j];
                List<Integer> list = new ArrayList<>();
                if (map.containsKey(sum)) {
                    list = map.get(sum);
                    list.add(i);
                    list.add(j);
                    map.put(sum, list);
                } else {
                    list.add(i);
                    list.add(j);
                    map.put(sum, list);
                }
            }
        }

        for (int k = 0 ; k<nums.length ; k++) {
            if (map.containsKey(0-nums[k])) {
                List<Integer> list = map.get(0-nums[k]);
                for (int index = 0 ; index+1<list.size() ; index = index+2) {
                    Integer i = list.get(index);
                    Integer j = list.get(index+1);
                    if (i!=j && i!=k && j!=k) {
                        List<Integer> resultList = new ArrayList<>(); 
                        resultList.add(nums[i]);
                        resultList.add(nums[j]);
                        resultList.add(nums[k]);
                        if (!existSameList(result, resultList)) {
                            result.add(resultList);
                        }
                    }
                }
            }
        }
        return result;
    }

    public boolean existSameList(List<List<Integer>> list, List<Integer> add) {
        if (list.size() == 0) return false;
        boolean result = true;
        add.sort((x,y) -> x-y);
        for (List<Integer> l: list) {
            l.sort((x,y) -> x-y);
            result = true;
            for (int i = 0 ; i<l.size() ; i++) {
                if (l.get(i) != add.get(i)) {
                    result = false;
                    break;
                }
            }
            if (result) {
                break;
            }
        }
        return result;
    }
}

2.去看视频了,使用双指针法。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>(); 
        // 排序
        Arrays.sort(nums);
        // 双指针
        int left = 0;
        int right = 0;
        for (int i = 0 ; i<nums.length ; i++) {
            if (nums[i] > 0) return result;
            // 去重i
            if (i > 0 && nums[i] == nums[i-1]) continue;
            left = i+1;
            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 {
                    // 找到了等于0的三元组
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    result.add(list);

                    // 去重left
                    while(left<right && nums[left] == nums[left+1]) left++;
                    // 去重rigjt
                    while(left<right && nums[right] == nums[right-1]) right--;

                    left++;
                    right--;
                }
            }
        }

        return result;
    }   
}

18. 四数之和

18题目链接

1.直接看视频后,写代码的。

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        int left, right;
        // 排序
        Arrays.sort(nums);
        for (int i = 0 ; i<nums.length ; i++) {
            // 对i进行剪枝
            if (nums[i] > 0 && nums[i] > target) {
                return result;
            }
            // 对i去重
            if (i>0 && nums[i] == nums[i-1]) {
                continue;
            }
            for (int j = i+1 ; j<nums.length; j++) {
                // 对j去重
                if (j>i+1 && nums[j] == nums[j-1]) {
                    continue;
                }
                left = j+1;
                right = nums.length-1;
                while (left<right) {
                    // 防止int溢出
                    long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum > target) {
                        right--;
                    } else if (sum < target) {
                        left++;
                    } else {
                        // 将符合条件的四元组加入result
                        List<Integer> list = new ArrayList<>();
                        list.add(nums[i]);
                        list.add(nums[j]);
                        list.add(nums[left]);
                        list.add(nums[right]);
                        result.add(list);

                        // 对left去重
                        while (left<right && nums[left] == nums[left+1]) left++;
                        // 对right去重
                        while (left<right && nums[right] == nums[right-1]) right--;

                        left++;
                        right--;
                    }
                }
            }
        }
        return result;
    }
}

总结

哈希表主要使用的三种数据结构是:数组、set、map。

关键字就是看到 一个元素是否出现集合里

使用场景:

数组:限制数值的大小

set:没有限制数值的大小,存的值独一无二,只存一个

map:需要多存多个

参考资料

代码随想录

posted @ 2023-03-07 14:06  zzzzzzsl  阅读(22)  评论(0)    收藏  举报