• LeetCode 4Sum 4个数之和


    题意:这是继2sum和3sum之后的4sum,同理,也是找到所有4个元素序列,满足他们之和为target。以vector<vector<int>>来返回,也就是二维的,列长为4,有多少个序列就多少行,每行都是唯一的,且升序。

    思路:

    方法一:用类似3sum的方法,先确定下第1个元素,再确定第2个元素,剩下两个元素用“两个指针”。前提是已排序。这个方法主要是怎么去重,这里提供两种方法:

    1)用unordered_set,只要找到一个序列就检查里面有没有这样的序列,若没有就插入,这样保证了唯一性,最后再用迭代器遍历一次,逐个搬到vector中返回。

    2)这是我用的方法。假设有序列 a{-2,-2,-2,-1,-1,0,0,1,1,2,2  共11个元素,target=0。

      第1个元素取a[0],第2个元素取a[1],那么>1的所有两个数的组合会被“两个指针”所全部找到,而如果有重复的,都会是连续的重复,所以只要判断与上一个序列之中有一个值不同,就可以进行插入。(“两个指针”处的去重)

      接下来第2个元素会取a[2],但是a[1]=a[2],还有必要再试吗?不必要,看{-2,-2,a,b}=target,这里a和b已经将所有可能给试了,如果这此仍取a[2],那么仍然在试集合{-2,-2,a,b}中的a和b的值而已。这下如果重复了,就不一定会连续的重复了(可以自己列出),去重就麻烦了。所以第2个元素必须跳过已经扫过的值,也就是无论还有几个-2,直接跳过到-1。(第2个元素处的去重)

      第1个元素要取a[1]开始试吗?不用!道理同第2个元素的去重一样。所有以第1个元素为-2的序列已经都试出来了,再取-2也只是再找重复的序列,而且不是连续的。

     1 class Solution {
     2 public:
     3     vector<vector<int> > fourSum(vector<int> &num, int target) {
     4         sort(num.begin(), num.end());    //排序
     5         vector<int> group(4,10086);
     6         vector< vector<int> > ans;   
     7         int n=num.size(), sum, sum2, *pl, *pr, old1=10086,old2=-10086 ;//这里的old可以随便取值,特殊一点的都行
     8         for(int j=0; j<n-3; j++ )    //第1个元素
     9         {
    10             if(old1==num[j]) continue; else old1=num[j];
    11             for(int i=j+1; i<n-2; i++ )//第2个元素
    12             {
    13                 if(old2==num[i])    continue; else old2=num[i];
    14                 sum2 = target-num[i]-num[j] ;//寻找余下两数之和
    15                 pl = &num[i+1];//左指针
    16                 pr = &num[n-1];//右指针
    17                 while(pl!=pr)
    18                 {
    19                     sum = *pl + *pr;
    20                     if( sum == sum2 )
    21                     {
    22                         if( group[0]!=num[j] || group[1]!=num[i] || group[2]!=*pl || group[3]!=*pr )//只要有一个不同,便可添加
    23                         {
    24                             group[0] = num[j];
    25                             group[1] = num[i];
    26                             group[2] = *pl;
    27                             group[3] = *pr;
    28                             ans.push_back(group);
    29                         }
    30                         pl++;
    31                     }
    32                     else if( sum > sum2 )    pr--;
    33                     else    pl++;
    34                 }
    35             }
    36             old2=10086;
    37         }
    38         return ans;
    39     }
    40 };
    4Sum

      

    方法二:将序列中两两的和作为新的序列,那问题就转化为“求两个值的和”,也就是用“两个指针”法。这里的难点在于,找到和为target的新序列中的两个元素,如何找到他们原来的面目(4个元素)。还有个问题,元素会被你重复的利用。

    比如,有序列a{-1,-1,0,1,1},

    转成新序列{-2,-1,0,0,-1,0,0,1,1,2},

    新序列是这么来的{-1+-1,-1+0,-1+1,-1+1,-1+0,-1+1,-1+1,0+1,0+1,1+1},

    也就是{a[0]+a[1],a[0]+a[2], a[0]+a[3],a[0]+a[4] ,a[1]+a[2],a[1]+a[3],a[1]+a[4],a[2]+a[3],a[2]+a[4],a[3]+a[4]}。

    假如target=0,我们在新序列中找到 -1+1=0,但是他们是a[0]+a[2]+a[2]+a[4]。也就是说,a[2]被算了两次了,是不允许的。

    此方法还未实现,有空再想。

  • 相关阅读:
    苹果的HomeKit协议
    广州出游计划
    Qt学习博客推荐
    Log4Qt使用(三)在DailyRollingFileAppender类中增加属性mMaxBackupIndex
    QT中关于窗口全屏显示与退出全屏的实现
    键盘事件-----按下回车键则触发事件
    窗体显示/编码设置/开机启动/文件选择与复制/对话框等
    设置系统日期时间
    输入内容, 列出可选的项: QComboBox
    如何根据安装时缺失的文件查找对应的包
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4396994.html
Copyright © 2020-2023  润新知