Day6 | 454四数相加Ⅱ&383赎金信&15三数之和&18四数之和

87 阅读3分钟

四数相加Ⅱ LeetCode 454

题目链接:[LeetCode 454 - 中等]

思路

考虑了之前的两数相加,并且可能存在不同的数相加后得到相同数的情况,因此使用HashMap。

HashMap:

java
class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer,Integer> map = new HashMap<>();
        int result = 0;
        for(int num1:nums1){
            for(int num2:nums2){
                map.put(num1+num2,map.getOrDefault(num1+num2,0)+1);
            }
        }

        for(int num3:nums3){
            for(int num4:nums4){
                if(map.containsKey(-num3-num4)){
                    result += map.get(-num3-num4);
                }
            }
        }
        return result;
    }
}

总结

使用了之前的题目中学到的知识

赎金信 LeetCode 383

题目链接:[LeetCode 383 - 简单]

思路

第一想法是使用HashMap,原因如下:题目中magazine中的每个字符只能在ransomNote中,因此相同的字符的个数也需要记录。

HashMap:

java
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        HashMap<Character,Integer> map = new HashMap<>();

        for(int i=0;i<magazine.length();i++){
            char ch = magazine.charAt(i);
            map.put(ch,map.getOrDefault(ch,0)+1);
        }

        for(int i=0;i<ransomNote.length();i++){
            char ch = ransomNote.charAt(i);
            if(!map.containsKey(ch)){
                return false;
            }else{
                map.put(ch,map.get(ch)-1);
                if(map.get(ch)<0){
                    return false;
                }
            }
        }
        return true;
    }
}

总结

  1. 看了更高效的解题时,发现该题可以参考#242有效的字母异位词的方式,即采用数组作为哈希表。
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if (ransomNote.length() > magazine.length()) {
            return false;
        }
        int[] recond = new int[26];

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

        for(int i=0;i<ransomNote.length();i++){
            char ch = ransomNote.charAt(i);
            if(recond[ch - 'a']==0)
                return false;
            recond[ch - 'a']--;
        }
        return true;
    }
}

代码可以优化:

        for(char ch:magazine.toCharArray()){
            recond[ch - 'a']++;
        }
  1. 该解法也可以代码优化:
        for(int i=0;i<ransomNote.length();i++){
            char ch = ransomNote.charAt(i);
            if(!map.containsKey(ch)){
                return false;
            }else{
                map.put(ch,map.get(ch)-1);
                if(map.get(ch)<0){
                    return false;
                }
            }
        }

改为

        for(int i=0;i<ransomNote.length();i++){
            int v=map.getOrDefault(ransomNote.charAt(i),0);
            if(v == 0)
                return false;
            map.put(ransomNote.charAt(i),v-1);
        }

三数之和 LeetCode 15

题目链接:[LeetCode 15 - 中等]

思路

看到题目,有一些想法 ①需要对原数组进行排序 ②需要进行去重操作

O(n^2):

java
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length;i++){
            if(nums[i]>0)
                return result;
            if(i>0 && nums[i]==nums[i-1])
                continue;
            int left=i+1;
            int right=nums.length-1;

            while(left<right){
                if(nums[i]+nums[left]+nums[right]==0){
                    result.add(Arrays.asList(nums[i],nums[left],nums[right]));
                    while(left<right && nums[left]==nums[left+1])left++;
                    while(left<right && nums[right]==nums[right-1])right--;
                    left++;
                    right--;
                }else if(nums[i]+nums[left]+nums[right]>0){
                    right--;
                }else{
                    left++;
                }
            }
        }
        return result;
    }
}

总结

  1. 如何进行排序
Arrays.sort(nums);
  1. 如何进行去重操作
if(i>0 && nums[i]==nums[i-1]) continue;

while(left<right && nums[left]==nums[left+1])left++;
while(left<right && nums[right]==nums[right-1])right--;
  1. 代码的巧妙之处:简短的一句代码精简了循环,将=0的隐含的内容囊括。
if(nums[i]>0)return result;

四数之和 LeetCode 18

题目链接:[LeetCode 18 - 中等]

思路

看到题目,感觉和#15三数相加差不多,有一些想法 ①需要对原数组进行排序 ②需要进行去重操作 但是有一些需要注意的地方,在第二个for循环的时候,需要剪枝。

O(n^3):

java
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);

        for(int i=0;i<nums.length;i++){
            if(nums[i]>0 && nums[i]>target)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;
                int right = nums.length-1;
                while(left<right){
                    long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum==target){
                        result.add(Arrays.asList(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--;
                    }else if(sum>target){
                        right--;
                    }else if(sum<target){
                        left++;
                    }
                }
            }
        }
        return result;
    }
}

总结

  1. 非常重要的代码:long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];如果是int,会导致溢出