代码随想录算法训练营-day07-454. 四数相加 II、383. 赎金信、第15题. 三数之和、第18题. 四数之和

454. 四数相加 II

  1. 学习文章链接:
  2. 题目分析:
    1. 两数之和的进阶版本。因此与两数之和使用相同的方法。
  3. 代码:
class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer, Integer> map = new HashMap<>();
        int count = 0;
        for (int i : nums1) {
            for (int j : nums2) {
                if (map.containsKey(i + j)) {
                    map.put(i + j, map.get(i + j) + 1);
                } else {
                     map.put(i + j, 1);
                }
            }
        }
        for (int k : nums3) {
            for (int l : nums4) {
                if (map.containsKey(0 - k - l)) {
                    count += map.get(0 - k - l);
                }
            }
        }
        return count;
    }
}
  1. 心得:
    1. 这里使用的是map。

383. 赎金信

  1. 学习文章链接:
  2. 题目分析:
    1. 使用与有效的字母异位词的方法即可。
    2. 也可以使用哈希法,但是哈希法比数组法药耗费更多的空间。
  3. 代码:
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if (ransomNote.length() == 0 || magazine.length() == 0) return false;
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < ransomNote.length(); i++) {
            if (map.containsKey(ransomNote.charAt(i))) {
                map.put(ransomNote.charAt(i), map.get(ransomNote.charAt(i)) + 1);
            } else {
                map.put(ransomNote.charAt(i), 1);
            }
        }
        for (int i = 0; i < magazine.length(); i++) {
            if (map.containsKey(magazine.charAt(i))) {
                map.put(magazine.charAt(i), map.get(magazine.charAt(i)) - 1);
            }
        }
        for (int value : map.values()) {
            if (value > 0) return false;
        }
        return true;
    }
}
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        // 定义一个哈希映射数组
        int[] record = new int[26];

        // 遍历
        for(char c : magazine.toCharArray()){
            record[c - 'a'] += 1;
        }

        for(char c : ransomNote.toCharArray()){
            record[c - 'a'] -= 1;
        }
        
        // 如果数组中存在负数,说明ransomNote字符串总存在magazine中没有的字符
        for(int i : record){
            if(i < 0){
                return false;
            }
        }

        return true;
    }
}
  1. 心得:
    1. 重温了map的相关方法。

第15题. 三数之和

  1. 学习文章链接:
  2. 本题分析:
    1. 首先对数组进行排序,排序之后的数组更方便操作。
    2. 数组排序之后,如果每层的初始位置大于零,则一定不能满足三数之和为零。
    3. for循环遍历时,注意去重。
    4. 双指针处要添加去重逻辑。
    5. 最后返回结果集。
  3. 代码:
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length < 3) return res;
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) return res;                        //数组排序之后,如果起始位置都大于零,则三数之和不可能为零;
            if (i > 0 && nums[i] == nums[i - 1]) continue;      //注意这里去重的逻辑,注意是continue;
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                int temp = nums[i] + nums[left] + nums[right];  //注意不是数组下表的和
                if (temp > 0) {
                    right--;
                } else if (temp < 0) {
                    left++;
                } else {
                    LinkedList<Integer> path = new LinkedList<>();
                    path.add(nums[i]);
                    path.add(nums[left]);
                    path.add(nums[right]);
                    //result.add(Arrays.asList(nums[i], nums[left], nums[right]));   
                    //学一下这种表达方式
                    res.add(new ArrayList(path));
                    while (left < right && nums[right] == nums[right - 1]) right--;  //一定不要把left < rigt忘记,第一层的while只是初始条件。
                    while (left < right && nums[left] == nums[left + 1]) left++;     //一定不要把left < rigt忘记,第一层的while只是初始条件。
                    right--;
                    left++;
                }
            }
        }
        return res;
    }
}
  1. 心得:
    1. 注意和是数组的值,不要写成索引的值。

第18题. 四数之和

  1. 学习文章链接:
  2. 本题分析:
    1. 四数之和是在三数之和的基础上,再加一层for循环。
    2. 但是在第一步去重的逻辑上,相比三数之后,由0换成target,因此要加上一些条件(nums[i] >= 0 || target >= 0)。
  3. 代码:
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length < 4) return res;
        Arrays.sort(nums);
        
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > target && (nums[i] >= 0 || target >= 0)) return res;
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < nums.length; j++) {
                // // if (nums[j] > target && (nums[j] >= 0 || target >= 0)) return res;
                if (j > 0 && nums[j] == nums[j - 1]) continue;
                int left = j + 1;
                int right = nums.length - 1;
                while (left < right) {
                    int temp = nums[i] + nums[j] + nums[left] + nums[right];
                    if (temp > target) {
                        right--;
                    } else if (temp < target) {
                        left++;
                    } else {
                        res.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        while (left < right && nums[right] == nums[right--]) right--;
                        while (left < right && nums[left] == nums[left++]) left++;
                        right--;
                        left++;
                    }
                }
            }
            
        }
        return res;
    }
}
  1. 心得:
    1. 基于三数之和的框架。

你可能感兴趣的:(代码随想录算法训练营,算法,数据结构,leetcode,java)