Leetcode 15 三数之和

题目介绍:

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

思路:

1.暴力求解

使用3个for循环,找到所有相加等于零的vector,然后对每一个vector做一个sort后再判断是否相等,相等则erase

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//3个for循环,找到所有相加等于零的vector之后对每一个vector做一个排序然后判断是否相等,erase掉相同的元素
class Solution
{
public:
   vector<vector<int>> threeSum(vector<int>& nums)
   {
       vector<vector<int>> result;//保存最后结果
       vector<int> temp;//保存每一个找到的结果

       int len = nums.size();
       int sum = 0;
       for(int m = 0; m < len; m++)
       {
           for(int n = m + 1; n<len ; n++)
           {
               for(int o = n + 1; o < len; o++)
               {
                    sum = nums[m] + nums[n] + nums[o];
                    if(sum == 0)
                    {
                        temp.push_back(nums[m]);//将一个新的元素加到vector的最后面
                        temp.push_back(nums[n]);
                        temp.push_back(nums[o]);
                        result.push_back(temp);
                        temp.clear();
                    }
                    sum = 0;
               }
           }
       }
       int l = result.size();
       for(int x = 0; x < l; x++)
       {
            sort(result[x].begin(), result[x].end());//对,result保存的每一个数组进行排序
       }

       for(int y = 0; y < l; y++)
       {
           for(int z = y + 1; z < l; z++)
           {
               if(result[y] == result[z])
               {
                   result.erase(result.begin() + z);
                   l--;
                   z--;
               }
           }
       }
       return result;
   }
};

int main()
{
    vector<int> b = {0,0,0,0};
    Solution a;
    vector<vector<int>> result = a.threeSum(b);
    for(int i=0; i<result.size(); i++)
    {
        cout << "{" ;
        for(int j=0; j<result[i].size(); j++)
        {
                cout << result[i][j] << ",";
        }
        cout << "}" << endl;
    }

    return 0;
}


2.对输入的数字先做一个排序,对负数部分进行循环, 看其后面的两数相加是否能与它抵消,当然如果第一个数就是正数就是无解的输入 。在计算后面两数的和的时候我们可以设两个迭代器, 一个从这个数后第一个数开始,一个从最后一个数开始, 如果加和小了就移动第一个迭代器,如果加和大了就移动第二个迭代器,就可以遍历所有情况了。 而且因为数字整个都是排序的,如果有重复数字肯定是相邻的, 我们在处理完前一个数之后,如果后一个数与之相等就删掉,这样避免了重复情况的出现。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*对输入的数字先做一个排序,对负数部分进行循环,
 * 看其后面的两数相加是否能与它抵消,当然如果第一个数就是正数就是无解的输入
 * 在计算后面两数的和的时候我们可以设两个迭代器,
 * 一个从这个数后第一个数开始,一个从最后一个数开始,
 * 如果加和小了就移动第一个迭代器,如果加和大了就移动第二个迭代器,就可以遍历所有情况了。
 * 而且因为数字整个都是排序的,如果有重复数字肯定是相邻的,
 * 我们在处理完前一个数之后,如果后一个数与之相等就删掉,这样避免了重复情况的出现。
 */

class Solution
{
public:
   vector<vector<int>> threeSum(vector<int>& nums)
   {
       vector<vector<int>> res;//保存最后结果
       sort(nums.begin(), nums.end());//升序,一般情况第一个就是这个数组里面最小的一般小于等于0
       for(int k = 0; k < nums.size(); ++k)
       {
            if(nums[k] > 0)
                break;//结束整个循环
            if(k > 0 && nums[k] == nums[k-1])
                continue;//结束本次循环

            int target = 0-nums[k];//第一次把元素 变成正数
            int i = k+1, j = nums.size()-1;//i指向下一个元素,j指向最后一个元素

            while(i < j)
            {
                if(nums[i] + nums[j] == target)//找到符合要求的值,可以看出a + b + c = 0 转化为 判断 a+b是否等于c
                {
                    res.push_back({nums[k], nums[i], nums[j]});
                    /*因为数字整个都是排序的,如果有重复数字肯定是相邻的,我们在处理完前一个数之后,如果后一个数与之相等就删掉,这样避免了重复情况的出现。*/
                    while(i < j && nums[i] == nums[i+1]) ++i;
                    while(i < j && nums[j] == nums[j-1]) --i;
                    ++i;
                    --j;
                }
                else if(nums[i] + nums[j] < target) ++i;
                else --j;
            }
       }
       return res;
   }
};

int main()
{
    vector<int> b = {-1, 0, -1, 2, 1, -4};
    Solution a;
    vector<vector<int>> result = a.threeSum(b);
    for(int i=0; i<result.size(); i++)
    {
        cout << "{" ;
        for(int j=0; j<result[i].size(); j++)
        {
                cout << result[i][j] << ",";
        }
        cout << "}" << endl;
    }

    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值