代码随想录Day7-哈希表02 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

454. 四数相加 II

        这题我上来就暴力解,结果就超时了,qwq

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int n = nums1.length, a = 0, b = 0, count = 0;
        int[] nums12 = new int[n*n];
        int[] nums34 = new int[n*n];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                nums12[a++] = nums1[i] + nums2[j];
            }
        }
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                nums34[b++] = nums3[i] + nums4[j];
            }
        }
        for(int i = 0; i < n*n; i++){
            for(int j = 0; j < n*n; j++){
                if(nums12[i] + nums34[j] == 0){
                    count++;
                }
            }
        }
        return count;
    }
}

        经过一番深思熟虑(参考官解,读书人的事。。dddd),选择用hashmap存nums1+nums2的数据,如果得到相同的数据,给对应value值+1就行了。

        用到了getOrDefault方法,

  getOrDefault(Object key, V defaultValue)方法返回指定的键映射的值,或 defaultValue如果这个Map不包含的键映射。

        把defaultValue设置成0,在得到值后+1,就可以实现键存在时值+1,不存在时创建键值对了。

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        HashMap h = new HashMap<>();
        //把nums1+nums2数据存到map中,遇到相同的数据该数据对应value值+1
        for(int i : nums1){
            for(int j : nums2){
                h.put(i+j, h.getOrDefault(i+j, 0)+1);
            }
        }
        int count = 0;
        //在nums3+nums4中找能跟map中的值相加为0的,这里表现为相反数
        for(int i : nums3){
            for(int j : nums4){
                if(h.containsKey(-i-j)){
                    count += h.get(-i-j);
                }
            }
        }
        return count;
    }
}

383. 赎金信

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        HashMap h = new HashMap<>();
        //把俩字符串都变成小字符串,只含一个字符的那种
        //不知道为啥要变成小字符串,变成char不香吗
        //变char的见本题第三个代码
        String[] r = ransomNote.split("");
        String[] m = magazine.split("");
        //对于m里的每个小字符串添加到map里,不存在值就是1,存在就+1
        for(String i : m){
            h.put(i, h.getOrDefault(i, 0)+1);
        }
        //遍历r,去map里找,没有直接false,有就值-1直到0就remove
        for(String i : r){
            if(!h.containsKey(i)){
                return false;
            }else{
                int value = h.get(i)-1;
                h.put(i, value);
                if(value == 0){
                    h.remove(i);
                }
            }
        }
        return true;
    }
}

        执行用时:38 ms, 在所有 Java 提交中击败了5.01%的用户。喵的,只能说很卑微了,这个执行用时5555,不就遍历了一遍嘛!偷看下官解

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if (ransomNote.length() > magazine.length()) {
            return false;
        }
        //两个字符串变成字符数组
        char[] r = ransomNote.toCharArray();
        char[] m = magazine.toCharArray();
        //把m里字符都按照字母表顺序存在新建数组里,a对应就是0…
        int[] alp = new int[26];
        for (char c : m) {
            alp[c - 'a']++;
        }
        //遍历r,去新数组里找有没有这个字符,没有就false,有就-1
        for (char c : r) {
            alp[c - 'a']--;
            if(alp[c - 'a'] < 0) {
                return false;
            }
        }
        return true;
    }
}

        经过这个题发现自己很擅长把简单问题复杂化,真的谢。

        官解就是写了个数组存个数,毕竟就26个字母,也存的过来,我咋没想到呢,就很容易被一些条条框框约束到,比如说今天做的哈希题目,自从第一题被哈希教育了之后,就非要哈希不可了。。以后还是要,发!散!思!维!可以多看看别人怎么想的,就算自己没时间重新写一遍了,但是至少要学习一些思路~

        看了题解之后很不服气的我把String改成了Charater。

        于是:执行用时:12 ms, 在所有 Java 提交中击败了21.05%的用户。

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        HashMap h = new HashMap<>();
        char[] r = ransomNote.toCharArray();
        char[] m = magazine.toCharArray();
        for(char i : m){
            Character c = new Character(i);
            h.put(c, h.getOrDefault(c, 0)+1);
        }
        for(char i : r){
            Character c = new Character(i);
            if(!h.containsKey(c)){
                return false;
            }else{
                int value = h.get(c)-1;
                h.put(c, value);
                if(value == 0){
                    h.remove(c);
                }
            }
        }
        return true;
    }
}

        happy happy happy,比原来进步了,看来String比起char来就是又占内存又费时间

​​​​​​15. 三数之和

        真醉了,又是只会暴力解,干脆没写代码,反正肯定超时5555

        直接上题解:三数之和 - 三数之和 - 力扣(LeetCode)

        真没想到第三个循环可以反着遍历,欸。

        对着官解注释哭着写:

class Solution {
    public List> threeSum(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);
        List> ans = new ArrayList>();
        // 枚举 a
        for (int first = 0; first < n; first++) {
            // 需要和上一次枚举的数不相同
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            // c 对应的指针初始指向数组的最右端
            int third = n - 1;
            int target = -nums[first];
            // 枚举 b
            for (int second = first + 1; second < n; second++) {
                // 需要和上一次枚举的数不相同
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                // 需要保证 b 的指针在 c 的指针的左侧
                while (second < third && nums[second] + nums[third] > target) {
                    third--;
                }
                // 如果指针重合,随着 b 后续的增加
                // 就不会有满足 a+b+c=0 并且 b list = new ArrayList();
                    list.add(nums[first]);
                    list.add(nums[second]);
                    list.add(nums[third]);
                    ans.add(list);
                }
            }
        }
        return ans;
    }
}



18. 四数之和

        跟上一题思路类似,直接看题解吧:四数之和 - 四数之和 - 力扣(LeetCode)

        下次可以把上面两题再写一遍思路!思路!

你可能感兴趣的:(散列表,数据结构,leetcode,算法,java)