【吃饭香系列】二周目|代码随想录算法训练营第七天|454.四数相加II |383. 赎金信 |15. 三数之和 |18. 四数之和

【吃饭香系列】二周目|代码随想录算法训练营第七天|454.四数相加II |383. 赎金信 |15. 三数之和 |18. 四数之和

第三章 哈希表part02

一、核心目标

今天我们的核心任务是掌握:

● 454.四数相加II

● 383. 赎金信

● 15. 三数之和

● 18. 四数之和

454.四数相加II

建议:本题是 使用map 巧妙解决的问题,好好体会一下 哈希法 如何提高程序执行效率,降低时间复杂度,当然使用哈希法 会提高空间复杂度,但一般来说我们都是舍空间 换时间, 工业开发也是这样。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0454.四数相加II.html

cpp 复制代码
class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        
        unordered_map <int,int> sum1;//key:a+b的数值,value:a+b数值出现的次数

        for(int a:nums1)// 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中
            {
                for(int b:nums2)
                sum1[a+b]++;
            }
        int count=0;// 统计a+b+c+d = 0 出现的次数,里面的(0-(c+d))是找出map中相同的key
        for(int c:nums3)// 再遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
            for(int d:nums4)
            if(sum1.find(0-(c+d))!=sum1.end())
            count+=sum1[(0-(c+d))];
    return count;
    }
    
};

383. 赎金信

建议:本题 和 242.有效的字母异位词 是一个思路 ,算是拓展题

题目链接/文章讲解:https://programmercarl.com/0383.赎金信.html

cpp 复制代码
class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int record[26]={0};

        if(ransomNote.size()>magazine.size())
        return false;

        for(int i=0;i<magazine.size();i++)
            record[magazine[i]-'a']++;

        for(int j=0;j<ransomNote.size();j++)
            {   
                record[ransomNote[j]-'a']--;
                if(record[ransomNote[j]-'a']<0)
                return  false;

            }
        
        return true;
        
    }
};

总结

有效的字母异位词 一个类型。都是哈希数组另放,然后范围大的样例数组先在哈希里++,范围小的--,发现负数就说明不匹配。

  1. 三数之和

建议:本题虽然和 两数之和 很像,也能用哈希法,但用哈希法会很麻烦,双指针法才是正解,可以先看视频理解一下 双指针法的思路,文章中讲解的,没问题 哈希法很麻烦。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0015.三数之和.html

cpp 复制代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;

        sort(nums.begin(),nums.end());
//剪枝
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]>0)
            return result;
//正确去重不会漏掉-1,-1,2 这种情况
            if(i>0&&nums[i]==nums[i-1])
            continue;

            int left=i+1;
            int right=nums.size()-1;

            while(right>left)
            {
                if(nums[i]+nums[left]+nums[right]>0)right--;
                else if(nums[i]+nums[left]+nums[right]<0)left++;
                else
                {
                    result.push_back(vector<int>{nums[i],nums[left],nums[right]});
                    while(right>left&&nums[right]==nums[right-1])right--;
                    while(right>left&&nums[left]==nums[left+1])left++;

                    right--;
                    left++;
                }
            }


        }
return result;

    }
};

总结

  1. 四数之和

建议: 要比较一下,本题和 454.四数相加II 的区别,为什么 454.四数相加II 会简单很多,这个想明白了,对本题理解就深刻了。 本题 思路整体和 三数之和一样的,都是双指针,但写的时候 有很多小细节,需要注意,建议先看视频。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0018.四数之和.html

cpp 复制代码
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());
        
        for(int k=0;k<nums.size();k++)
        {
            if(nums[k]>target&&target>0)
            break;

            if(k>0&&nums[k]==nums[k-1])
            continue;

            for(int i=k+1;i<nums.size();i++)
            {
                if(nums[k] + nums[i] > target && nums[k] + nums[i] >= 0)
                break;

                if(i>k+1&&nums[i]==nums[i-1])
                continue;

                int left=i+1;
                int right=nums.size()-1;
                
                while(left<right)
                {
                    if((long)nums[k]+nums[i]+nums[left]+nums[right]>target) right--;
                    else if((long)nums[k]+nums[i]+nums[left]+nums[right]<target) left++;
                    else
                    {
                        result.push_back(vector<int>{nums[k],nums[i],nums[left],nums[right]});
                        while(left<right&&nums[right]==nums[right-1])right--;
                        while(left<right&&nums[left]==nums[left+1])left++;
                        right--;
                        left++;
                    }

                }


            }


        }
        return result;
    }
};

总结

在三数之和上面多套了一层循环,容易出现以下问题

1、

2、

相关推荐
爱理财的程序媛6 小时前
openclaw 盯盘实践
算法
MobotStone9 小时前
Google发布Nano Banana 2:更快更便宜,图片生成能力全面升级
算法
颜酱12 小时前
队列练习系列:从基础到进阶的完整实现
javascript·后端·算法
用户57573033462412 小时前
两数之和:从 JSON 对象到 Map,大厂面试官到底在考察什么?
算法
程序猿追12 小时前
“马”上行动:手把手教你基于灵珠平台打造春节“全能数字管家”
算法
ZPC82101 天前
docker 镜像备份
人工智能·算法·fpga开发·机器人
ZPC82101 天前
docker 使用GUI ROS2
人工智能·算法·fpga开发·机器人
琢磨先生David1 天前
Day1:基础入门·两数之和(LeetCode 1)
数据结构·算法·leetcode
颜酱1 天前
栈的经典应用:从基础到进阶,解决LeetCode高频栈类问题
javascript·后端·算法