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

  1. 四数相加 II
  2. 赎金信
  3. 三数之和
  4. 四数之和

454. 四数相加 II

第一想法

  • 这是一个数据无相关性的四个数组,只要每个数组都顺序遍历,就能找到符合条件的答案,不用考虑重复性。所以,只要考虑如何减少时间复杂度就好。如果是暴搜,就是四重循环,不太行。
  • 那么考虑一下先算前两个数组,再算后两个数组,看是否有为相反数的存在。本题值需要返回个数,而不需要返回下标,所以只要记下来每个结果出现几次,然后找到相符的就可以

代码

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

383. 赎金信

第一想法

第一个string中每个字母出现的次数,一定小于第二个string中每个字幕出现的次数。所以统计一下第二个string每个字母出现多少次,然后遍历第一个string,看最后的结果是否有没出现过的字母或者出现次数不够即可。统计次数和快速查找字幕出现次数适合用unordered_map

代码

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        if (ransomNote.size() > magazine.size()) return false;
        unordered_map<char, int> map;
        for (auto a: magazine) map[a] ++;
        for (auto b: ransomNote){
            if (map.find(b) == map.end() || map[b] == 0) 
                return false;
            map[b] --;
        }
        return true;
    }
};

15. 三数之和

第一想法

题目返回的是不重复出现的和为0的三个数数值,所以不管怎么搜索,其实最重要的是去重。

  • 第一种想法是直接对数组去重,然后找相加为0的数值。
  • 第二种想法是,三个指针i, j, k遍历去寻找,如果找到nums[i] == nums[i-1]则要去重,这样其实是在- 1 -1 2遍历到第二个-1时进行去重,第一个遍历的时候是可以保留结果的。

代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
    // -4 -1 -1 0 1 2
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); i ++){
            if (i && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1, k = nums.size() - 1; j < k; j ++){
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                while (j < k - 1 && nums[i] + nums[j] + nums[k] > 0) 
                    k --;
                if (nums[i] + nums[j] + nums[k] == 0)
                    res.push_back({nums[i], nums[j], nums[k]});
            }
        }
        return res;
    }
};

18. 四数之和

第一想法

和三数之和一样,只不过要多加一层循环。

代码

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        for (int i = 0; i < nums.size(); i ++){
            if (i && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < nums.size(); j ++){
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                for (int k = j + 1, z = nums.size() - 1; k < z; k++){
                    if (k > j + 1 && nums[k] == nums[k - 1]) 
                        continue;
                    while (k < z - 1 && (long long)nums[i] + nums[j] + nums[k] + nums[z] > target) z--;
                    if ((long long)nums[i] + nums[j] + nums[k] + nums[z] == target) 
                        res.push_back({nums[i], nums[j], nums[k], nums[z]});
                }

            }
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值