3Sum
题目:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
题意:
在一个给定的数组中找寻满足条件的集合,条件为3个数和值为0。
题目给定了示例。
思路:
方法1:排序给定序列,然后每次轮寻并且固定一个数值,在另外剩下的序列里面查找两个和值为固定值相反数的值,由于是已经排序的,轮寻时轮寻到固定值大于等于0我们就可以退出循环,因为是已经排序的,可以考虑下。
方法2:也是通用的解 K Sum的解法,比如3 Sum,我们解决过2 Sum的问题,那么就固定一个数值,然后解决2 Sum即可,如果是K Sum,就递归实现从2 Sum解决开始。
方法3:暴力求解法,O(n^3),就不说了。
代码:
方法1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
vector<vector<int>> threeSum(vector<int>& nums)
{
//用set原因是我们不能找寻重复的
set<multiset<int>>sst;
vector<vector<int>>ret;
//特殊情况如果为空退出
if(nums.size() == 0){
return ret;
}
//排序
sort(nums.begin(), nums.end());
//特殊情况如果全是负值就直接退出
if(*(nums.end()-1) <= 0){
return ret;
}
for(auto iter = nums.begin(); *iter <= 0; ++iter)
{
//设置求2 Sum的目标值
int target = 0 - *iter;
//由于是已经排序的,我们让迭代器分别为起始和末尾,比较起始和末尾的和值,如果小于target,变换起始迭代器加1,总sum值变大,再次比较,如果大于target,那么尾迭代器减1,总sum值变小。直到首尾迭代器相等。
auto iter2 = iter+1;
auto iter3 = nums.end()-1;
while(iter2 != iter3)
{
int sum = *iter2 + *iter3;
if(sum < target)
{
++iter2;
}
else if(sum > target)
{
--iter3;
}
else if(sum == target)
{ //找到了
multiset<int>st;
st.insert(*iter);
st.insert(*iter2);
st.insert(*iter3);
sst.insert(st);
++iter2;
--iter3;
if(iter2 - iter3 == 1){
break;
}
}
}
}
for(const multiset<int>&s : sst){
vector<int>tmp;
for(int i : s){
tmp.push_back(i);
}
ret.push_back(tmp);
}
return ret;
}
int main(int argc, char *argv[])
{
vector<int>ivec = {-1, 0, 1, 2, -1, -4};
auto ret = threeSum(ivec);
for(vector<int>&ivt : ret){
for(int i : ivt){
cout << i << " ";
}
cout << endl;
}
return EXIT_SUCCESS;
}
这段代码在leetcode上没有通过,原因是超时了Time Limit
Exceeded,代码的原因大概是因为set和multiset的缘故吧,插
入还是比较浪费时间的,我不去细纠了,感兴趣大家可以改下不借
助set,我是偷了个懒。^_^