Day4(1)Leetcode 454四数相加II (2)Leetcode 383赎金信 (3)三数之和

1. Leetcode 454四数相加II

(1)解析

Leetcode454
参考文章

(2)思路

本题解题步骤:
首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
最后返回统计值 count 就可以了

(3)代码

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map <int, int> maplist;
        for(int num1 : nums1)
            for(int num2 : nums2)
            {
                maplist[num1 + num2]++;
            }
        int cnt = 0;
        for(int num3 : nums3)
            for(int num4 : nums4)
            {
                if(maplist.find(-(num3+num4)) != maplist.end())
                {
                    cnt += maplist[-(num3 + num4)];
                }
            }
        return cnt;
    }
};

(4)总结

a.建立unordered_map<typename,int> ,即建立基本类型到int的映射,重要的是,默认任何int型的数据的一开始的映射值均为0,这点非常常用,可以直接使用
b.cnt += maplist[-(num3 + num4)]这点值得注意,maplist[-(num3 + num4)]的value值可能大于1,也就是存在多组相同和的num1+num2

2. Leetcode 383赎金信

(1)解析

Leetcode383
参考文章

(2)思路

这道题目和242.有效的字母异位词 (opens new window)很像,242.有效的字母异位词 (opens new window)相当于求 字符串a 和 字符串b 是否可以相互组成 ,而这道题目是求 字符串a能否组成字符串b,而不用管字符串b 能不能组成字符串a。
a.“为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思” 这里说明杂志里面的字母不可重复使用。
b.“你可以假设两个字符串均只含有小写字母。” 说明只有小写字母,这一点很重要,可以采用空间换取时间的哈希策略, 用一个长度为26的数组还记录magazine里字母出现的次数。

(3)代码

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int maplist[26] = {0};
        if(ransomNote.size() > magazine.size())
            return false;
        for(int i : magazine)
            ++maplist[i - 'a'];
        for(int j : ransomNote)
        {
            --maplist[j - 'a'];
            if(maplist[j - 'a'] < 0)
                return false;
        }
        return true;
    }
};

(4)总结

和有效的字母异位词区别在于最后判断false的条件不一样。

3. Leetcode 15 三数之和

(1)解析

Leetcode15
参考文章

(2)思路

双指针,首先将数组排序,然后有一层for循环,i从下标0的地方开始,同时定一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上,left和right指针往中间移动直到相遇为止。

(3)代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> resVec;
        sort(nums.begin(), nums.end());
        for(int i = 0 ; i < nums.size(); ++i)
        {
            if(nums[i] > 0)
                break;
            if(i > 0 && nums[i] == nums[i-1])
                continue;
            int left = i + 1;
            int right = nums.size() - 1;
            while(left < right)
            {
                while(left < right && nums[left] + nums[right] > -nums[i])
                {
                    --right;
                }
                while(left < right && nums[left] + nums[right] < -nums[i])
                {
                    ++left;
                }
                if(left < right && nums[left] + nums[right] == -nums[i])
                {
                    resVec.push_back(vector<int>{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;
                }
            }
        }
        return resVec;
    }
};

(4)总结

a.数组首先排序
b.nums[i] > 0预先判断去掉无意义操作
c. if(i > 0 && nums[i] == nums[i-1]),元素i去重很巧妙,针对-1,-1,2这样的组合
d.左右指针的去重在找到三元组之后,左右指针去重无需考虑c中的问题,nums[left]==nums[left + 1],nums[right]==nums[right-1]
e.if的判断条件,left<right应放前面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值