【吃饭香系列】二周目|代码随想录算法训练营第七天|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、

相关推荐
小O的算法实验室2 小时前
2025年COR SCI2区,考虑风场影响的无人机搜救覆盖路径规划精确界算法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
xqqxqxxq2 小时前
洛谷算法1-3 暴力枚举(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
_OP_CHEN2 小时前
【算法基础篇】(五十五)卡特兰数封神之路:从括号匹配到二叉树构造,组合数学的万能钥匙!
算法·蓝桥杯·c/c++·组合数学·卡特兰数·算法竞赛·acm/icpc
郝学胜-神的一滴2 小时前
Python美学的三重奏:深入浅出列表、字典与生成器推导式
开发语言·网络·数据结构·windows·python·程序人生·算法
2501_901147832 小时前
学习笔记:基于摩尔投票法的高性能实现与工程实践
笔记·学习·算法·性能优化
春日见2 小时前
window wsl环境: autoware有日志,没有rviz界面/ autoware起不来
linux·人工智能·算法·机器学习·自动驾驶
rainbow68892 小时前
PCL点云处理算法全解析
算法
代码无bug抓狂人2 小时前
C语言之可分解的正整数(蓝桥杯省B)
c语言·开发语言·算法
量子-Alex2 小时前
【大模型技术报告】Seed-Thinking-v1.5深度解读
人工智能·算法