• 2:set和map解决力扣题


    一:数组两数之和等于给定值

     这里要考虑的细节:

    • 索引---这里是从0开始计算还是1开始
    • 解的存在与唯一---没有解怎么办?有多个解怎么办
    1. #include
    2. #include
    3. using namespace std;
    4. /*
    5. 给定一个整形数组nums:
    6. 对于该数组的两个索引i,j(i≠j),使得nums[i]+nums[j]==target(给定的)
    7. 求出要求的i,j值-----即函数返回结果
    8. */
    9. /*
    10. 思路---将所有元素放入查找表中,之后对每一个元素a,检查target-a的存在性
    11. 数据结构---map:k存放元素值,v对应着元素的索引(我们要返回的结果)
    12. */
    13. class soluction{
    14. public:
    15. vector<int> twoSum(vector<int>& nums,int target){
    16. //函数传入:数组和目标值,返回结果:满足条件的两个索引
    17. unordered_map<int,int> record;//只实现查找,哈希表类型即可
    18. for(int i=0;isize();i++){
    19. int find_num=target-nums[i];
    20. //在当前的record中查找是否存在满足条件的:find_num
    21. if(record.find(find_num)!=record.end()){//找到了
    22. //所求下标为--当前索引,record存放的v值
    23. int res[2]={record[find_num],i};
    24. return vector<int>(res,res+2);
    25. }
    26. record[nums[i]]=i;//k存放元素值,v存放索引
    27. }
    28. throw invalid_argument("no soluction!");//无解,抛出异常
    29. }
    30. };

     测试程序:

    1. #include"two_sum.h"
    2. #include
    3. using namespace std;
    4. int main(){
    5. vector<int> arr={1,8,9,4,7,2,6,3,5};
    6. int target=14;
    7. vector<int> sum=soluction().twoSum(arr,target);
    8. for(int i=0;isize();i++){
    9. cout<" ";
    10. }
    11. return 0;
    12. }

    注意---数组转换成vector

        int ary[]={1,8,9,4,7,2,6,3,5};

        vector vec(ary, ary + sizeof(ary) / sizeof(int));


    算法思想:

    用map作为查找表:k存放元素,i存放索引

    由于一次性全部将“元素值-索引”存放map时,如果有相同的元素时会发生覆盖。

    所以:每次取一个元素,计算出待查找的值大小,如果没找到,才把该元素放入查找表map中,这时候覆盖就无所谓了,毕竟元素值不会变

     二:四个数组中各取一个元素相加为0的所有可能

     

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. class soluction{
    6. public:
    7. int fourSumTotal(vector<int>& a,vector<int>& b,vector<int>& c,vector<int>& d){
    8. //传入四个数组,返回可能情况的个数
    9. /*题目要求四个数组元素个数相同,所以要设置断言*/
    10. assert(a.size()==b.size()&&a.size()==c.size()&&b.size()==c.size());
    11. /*
    12. 代码思路:
    13. 首先将数组a和数组b相加的所有和作为:k,出现频次记作:v
    14. 然后逐个遍历数组c和数组d,判断是否满足条件
    15. */
    16. //1:创建查找表
    17. map<int,int> record;
    18. for(int i=0;isize();i++)
    19. for(int j=0;jsize();j++)
    20. record[a[i]+b[j]]++;
    21. //2:遍历求解
    22. int res=0;//返回结果
    23. for(int i=0;isize();i++)
    24. for(int j=0;jsize();j++)
    25. if(record.find(-c[i]-d[j])!=record.end()){
    26. res+=record[-c[i]-d[j]];
    27. }
    28. return res;
    29. }
    30. };
    1. #include"4sum.h"
    2. #include
    3. #include
    4. using namespace std;
    5. int main(){
    6. vector<int> aa={1,2};
    7. vector<int> bb={-1,-2};
    8. vector<int> cc={5,6};
    9. vector<int> dd={-5,-6};
    10. cout<<soluction().fourSumTotal(aa,bb,cc,dd)<
    11. return 0;
    12. }

    思路很清晰:只要知道了要存什么,即可求出结果

    1. int dist(const pair<int,int>& a,const pair<int,int>& b){
    2. return (a.first-b.first)*(a.first-b.first)+
    3. (a.second-b.second)*(a.second-b.second);
    4. }
    5. int main(){
    6. vectorint,int>> m={{0,0},{1,0},{2,0}};
    7. cout<<dist(m[0],m[2])<
    8. return 0;
    9. }

     注意:取出整个点,直接用:变量名【下标】

     三:点距离相等的可能

     思路:

     把点i看成一个枢纽,求出所有点到点i的距离

    ----------利用map存储,k存放距离,v存放个数

    ----------只要v大于2就可以找到两个点,剩下的就是排列组合问题

    vector存储pair对用法 

    1. vectorint,int>> m={{1,2},{2,3},{4,2}};
    2. /*遍历方式*/
    3. //1:下标
    4. for(int i=0;isize();i++){
    5. cout<","<
    6. }
    7. //2:迭代器
    8. vectorint,int>>::iterator iter;
    9. for(iter=m.begin();iter!=m.end();iter++){
    10. cout<first<<","<second<
    11. cout<<(*iter).first<<","<<(*iter).second<
    12. }

     首先先看:vector<pair<类型,类型>>的遍历方式

    第一种:变量名[下标].first//second

    第二种:迭代器---(iter*).first//second 或 iter->first//second

    1. int main(){
    2. vectorint,int>> m;
    3. m.push_back({1,2});
    4. m.push_back({3,4});
    5. /*遍历方式*/
    6. for(int i=0;isize();i++){
    7. cout<","<
    8. }
    9. return 0;
    10. }

    加入元素:push_back({a,b})

    首先这里需要对这个基准点做出选择,实际上点i有数组长度种可能,所以每一种可能都要创建一种查找表,然后在查找表内挑出符合题目要求的 

    1. int dist(const pair<int,int>& a,const pair<int,int>& b){
    2. return (a.first-b.first)*(a.first-b.first)+
    3. (a.second-b.second)*(a.second-b.second);
    4. }
    5. int main(){
    6. vectorint,int>> m={{1,1},{1,2},{2,1},{4,5},{5,4}};
    7. for(int i=0;isize();i++){
    8. map<int,int> record;//在循环体内创建查找表
    9. for(int j=0;jsize();j++){
    10. if(j != i)//去除自己和自己计算可能
    11. record[dist(m[i],m[j])]++;
    12. }
    13. //遍历
    14. map<int,int>::iterator iter;
    15. for(iter=record.begin();iter!=record.end();iter++){
    16. cout<first<<","<second<
    17. cout<
    18. }
    19. return 0;
    20. }

     

    完整程序

    1. #include
    2. #include
    3. using namespace std;
    4. class soluction{
    5. private:
    6. //利用距离的平方计算,避免开根号产生误差,影响查找表的查找
    7. int dist(const pair<int,int>& a,const pair<int,int>& b){
    8. return (a.first-b.first)*(a.first-b.first)+
    9. (a.second-b.second)*(a.second-b.second);
    10. }
    11. public:
    12. int sameDist(vectorint,int>>& points){
    13. //传入参数是:pair的pair对,存放在vector<>中
    14. int res=0;//记录返回值
    15. for(int i=0;isize();i++){
    16. map<int,int> record;//记录所有点到i的距离
    17. for(int j=0;jsize();j++){
    18. if(j!=i)
    19. record[dist(points[i],points[j])]++;//别忘了频次累计
    20. }
    21. //遍历查找表
    22. map<int,int>::iterator iter;
    23. for(iter=record.begin();iter!=record.end();iter++){
    24. if(iter->second>=2)
    25. res+=(iter->second)*(iter->second-1);
    26. }
    27. }
    28. return res;
    29. }
    30. };
    1. #include"dist.h"
    2. #include
    3. using namespace std;
    4. int main(){
    5. vectorint,int>> m={{1,1},{1,2},{2,1},{4,5},{5,4}};
    6. cout<<soluction().sameDist(m);
    7. return 0;
    8. }

     四:滑动窗口和查找表

     

     思路:

    题目要求找两个值相同的索引,且距离不超过k

     也就是要找这样一个区间:【l,l+k】使得其中包含两个值相同的索引

     存在结束程序,如果区间不存在,那么就看下一个元素

     此时要把窗口左移,也就是l加一

     如果该元素与左移后的窗口依然没有重复元素,那么纳入该元素,l+k加一

     重复上述过程

    代码

    1. #include
    2. #include
    3. using namespace std;
    4. class soluction{
    5. public:
    6. bool get_indexes(vector<int>& nums,int k){
    7. set<int> record;
    8. for(int i=0;isize();i++){
    9. //每次访问一个元素,都要判断查找表中是否存在
    10. if(record.find(nums[i])!=record.end())
    11. return true;
    12. //不存在加入查找表,此时查找表没重复元素
    13. record.insert(nums[i]);
    14. //查看查找表尺寸,过节,删去最最左边元素
    15. if(record.size()==k+1)//ex:0~k是有k+1个数
    16. record.erase(nums[i-k]);//当前i是k,最左边为0
    17. }
    18. return false;
    19. }
    20. };
    1. #include"hdwindow.h"
    2. #include
    3. using namespace std;
    4. int main(){
    5. vector<int> m={1,2,3,4,5,6,7,2,3};
    6. int k=6;
    7. cout<<soluction().get_indexes(m,k);
    8. return 0;
    9. }
  • 相关阅读:
    IDEA 快捷键
    荧光标记氨基酸:荧光标记L-丙氨酸乙酯盐酸盐,L-Alanine ethyl ester hydrochloride labeled
    彻底理解闭包实现原理
    TabLayout+Fragment+ViewPager实现Tab页面效果
    以 ZGC 为例,谈一谈 JVM 是如何实现 Reference 语义的
    非零基础自学Java (老师:韩顺平) 第10章 面向对象编程(高级部分) 10.5 final关键字
    白平衡简介
    java随手记
    通过分离菌的胞外代谢组学推断生物结皮中微生物与代谢物关系
    详解机器学习高维数据降维方法
  • 原文地址:https://blog.csdn.net/weixin_47173597/article/details/126726939