【算法训练记录——Day07】

目标

● 454.四数相加II
● 383. 赎金信
● 15. 三数之和
● 18. 四数之和
● 总结

454.四数相加

在这里插入图片描述
思路:早上起来没有思路一脸懵,只想到了暴力破解
看了题解,搜嘎。转变成两数相加,前两个数一组,后两个数一组

	int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map<int, int> hash;
        int len = nums1.size();
        int count = 0;
        for(int i : nums1)
            for(int j : nums2)
                ++hash[0 - i - j];
        
        for(int i : nums3)
            for(int j : nums4)
                if(hash.find(i + j) != hash.end())
                    count += hash[i + j];
        
        return count;
    }

如果本题想难度升级:就是给出一个数组(而不是四个数组),在这里找出四个元素相加等于0,答案中不可以包含重复的四元组
思考:

383.赎金信

在这里插入图片描述
思路:ran里的所有字符都能在mag里找到。用unordered_map记录mag中字符及个数,遍历ran,从中寻找找到-1,找不到或小于0返回;

	bool canConstruct(string ransomNote, string magazine) {
        unordered_map<char, int> hash;
        for(char c : magazine) {
            ++hash[c];
        }
        for(char c : ransomNote) {
            if(hash[c] > 0){
               --hash[c];
            } else {
                return false;
            }
        }
        return true;
    }

其实在本题的情况下,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!(代码随想录)

	bool canConstruct(string ransomNote, string magazine) {
        int hash[26] = {0};
        for(char c : magazine) {
            hash[c-'a']++;
        }
        for(char c : ransomNote) {
            if(hash[c-'a'] > 0){
               --hash[c-'a'];
            } else {
                return false;
            }
        }
        return true;
    }

15.三数之和

在这里插入图片描述
思路:是的,又是做过但忘记的,怎么办,学而不思则罔,可我也思了呀。。。
应该还是hash保存nums[i] + nums[j] 的负数,然后去nums[k]中查询。但是下标要不相等,那就手动过滤

vector<vector<int>> threeSum(vector<int>& nums) {
        // vector<vector<int>> res;
        // int len = nums.size();

        // sort(nums.begin(), nums.end());
        // if(nums[0] > 0 || nums[len-1] < 0) 
        //     return res;

        // for(int i = 0; i < len; i++) {
        //     if (nums[i] > 0) break;
        //     if(i > 0 && nums[i] == nums[i - 1]) 
        //         continue;
        //     unordered_set<int> hash;

        //     for(int j = i + 1; j < len; j++) {
        //         if(j > i + 2 && nums[j-1] == nums[j] && nums[j-2] == nums[j])
        //             continue;
        //         int sum = 0 - nums[i] - nums[j];
        //         if(hash.find(sum) != hash.end()) {
        //             res.push_back({nums[i], nums[j], sum});
        //             hash.erase(sum);
        //         } else {
        //             hash.insert(nums[j]);
        //         }
        //     }
        // }
        // return res;
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] > 0) {
                return res;
            }
            // 正确去重a方法
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int left = i + 1;
            int right = nums.size() - 1;
            while(right > left) {
                if(nums[left] + nums[i] + nums[right] < 0) {
                    ++left;
                } else if (nums[left] + nums[i] + nums[right] > 0) {
                    --right;
                } else {
                    res.push_back({nums[i], nums[left], nums[right]});
                    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;
                    // 找到答案时,双指针同时收缩
                    right--;
                    left++;
                }
            }
        }
        return res;
    }

这里还是不太明白哈希法的去重逻辑
…把对应行注释后能清楚处理的什么场景,但是想不到为什么这么做

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值