算法Day2-三数之和

题目

给定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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值