算法Day2-三数之和

来源:互联网 发布:pl sql scott登录不了 编辑:程序博客网 时间:2024/05/22 03:09

题目

给定n个整数的一个数组S,S中是否有元素a,b和c满足a+b+c+0 ? 找出数组中所有满足加和为0的不同的三个数组合。注意:(a,b,c)中的元素必须是非降序的排列方式(即a<=b<=c)解决方案中给出的集合不能包含重复的三元组例如,给定的数组S={-1 0 1 2 -1 -4}一个解决方案集合是    {-1, 0, 1}    {-1, -1 ,2}

解析

本题为第一天题目两数之和的拓展,把2个变量变成了3个变量。对于一般的拓展问题,要通过一些转换将其还原为已有的问题,才能更好的处理。
对于本题,我们稍微把等式修改一下, a + b + c = 0 => a + b = -c。
这个时候,问题就转换为,寻找两个变量 a 和 b ,使得其之和为 -c , 又回到了“两数之和”的问题。

因为题目提到了可能出现重复解的问题,所以要注意“去重”。这次的代码的变化也体现在去重的方面。
1. 双指针扫描的去重。例如对于 [-2, 0, 0, 2, 2]。我们期待的结果是[-2, 0, 2],如果不去重的话,结果就是[-2, 0, 2],[-2, 0, 2]。因为对于数组的处理是先排序的,所以本种除重是判断当前start指针值是否与前一个指针值相等,或者当前end指针值是否与后一个指针值相等,如果相等,那么就不予考虑。
2. 外层循环去重。 比如[-2, -2, -2, 0, 2],包含三个-2。当在循环中处理完第一个 -2 以后,后面的两个就没有必要进行重复处理了。

完整代码

#include <iostream>#include <vector>#include <map>#include <algorithm>using namespace std;vector< vector<int> > threeSum(vector<int> &num){    sort(num.begin(), num.end());    vector< vector<int> > result;    int len = num.size();    for(int i=0; i<len; i++){        int target = 0 - num[i];        int start = i + 1, end = len - 1;        while(start < end){            if(num[start] + num[end] == target){                vector<int> solution;                solution.push_back(num[i]);                solution.push_back(num[start]);                solution.push_back(num[end]);                result.push_back(solution);                start++; end--;                //双指针扫描的去重                while(start<end && num[start] == num[start-1])                    start++;//如果下一个元素与上一个元素相等,那么跳过                while(start<end && num[end] == num[end+1])                    end--;//如果上一个元素和当前end相等,跳过这个            }            else if (num[start] + num[end] < target){                start++;            }            else{                end--;            }        }//end while        if(i<len-1){            //外层循环的去重            while(num[i] == num[i+1]) i++;        }    }//end for    //下面是输出    vector< vector<int> >::iterator iter1;    for(iter1 = result.begin(); iter1 != result.end(); iter1++)    {        vector<int> vTemp = *iter1;        vector<int>::iterator iter2;        for(iter2 = vTemp.begin(); iter2 != vTemp.end(); iter2++)        {            cout<<*iter2<<' ';        }        cout<<endl;    }    return result;}void main(){    int nums[] = {-1,0,1,2,-1,-4};//这里修改数组    vector<int> v;    for(int i=0; i<sizeof(nums) / 4; i++){        v.push_back(nums[i]);    }     threeSum(v);}

学习笔记

  1. 对于int型数组,使用 sizeof() 对其求长度,需要除以4。 对于sizeof()的C++Reference是这样定义的:

The sizeof operator is a compile-time operator that returns the size, in bytes, of the argument passed to it.
sizeof(int): 4
sizeof(float): 4
sizeof(double): 8
sizeof(char): 1

sizeof()是求的字节长度,int字符是四个字节,所以在求int型数组的时候需要除以它的单位字节长度。

2.对于使用迭代器输出 两层vector 嵌套型数据结构内容,代码如下:

vector< vector<int> >::iterator iter1;    for(iter1 = result.begin(); iter1 != result.end(); iter1++)    {        vector<int> vTemp = *iter1;        vector<int>::iterator iter2;        for(iter2 = vTemp.begin(); iter2 != vTemp.end(); iter2++)        {            cout<<*iter2<<' ';        }        cout<<endl;    }
0 0