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.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:

[

[-1, 0, 1],

[-1, -1, 2]

]


关于这个问题,我最初的想法很简单,就是暴力搜索所有数值,然后得到所有的和为0的子序列。但是这个做法的问题是会得到重复的序列,那么思考下去就是,判断得到的子序列是否与前面已经存下来的数据重复,如果重复则不存。

#include <iostream>
#include <vector> using namespace std; vector<vector<int> > threeSum(vector<int>& nums); bool compare(vector<int> &v1, vector<int>& v2); vector<vector<int> > threeSum(vector<int>& nums) {
vector< vector<int> >ret; if (nums.size() < 3) {
return ret;
} int size = nums.size(); for (vector<int>::const_iterator it = nums.cbegin(); it != (nums.cend() - 2); it++) {
int first = *it;
for (vector<int>::const_iterator it2 = it + 1; it2 != (nums.end() - 1); it2++) {
int second = *it2;
for (vector<int>::const_iterator it3 = it2 + 1; it3 != nums.end(); it3++) {
if (*it3 + second + first) {
continue;
} else {
vector<int> tmp;
tmp.push_back(first);
tmp.push_back(second);
tmp.push_back(*it3);
bool dump = false;
for (vector<vector<int> >::iterator itt = ret.begin(); itt != ret.end(); itt++) {
if (compare(tmp, *itt)) {
dump = true;
break;
}
} if (dump) {
continue;
}
ret.push_back(tmp);
cout<< *it3 << second << first <<endl;
}
} }
}
return ret;
} bool compare(vector<int> &v1, vector<int>& v2) {
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
bool ret = false;
for (vector<int>::iterator it2 = v2.begin(); it2 != v2.end(); it2++) {
if (*it == *it2) {
// cout<<*it2<<endl;
v2.erase(it2);
// cout<<*it2<<endl;
ret = true;
break;
}
}
if (!ret) {
return false;
}
}
return true;
}

这一坨玩意儿实际上是可行的,但是运行超时了,时间复杂度>O(n^5) 基本就是一坨垃圾了。

考虑新的计算方法,在计算中就规避掉会导致重复的情况。经过思考,重复的序列和重复的数字是有关系的,即当已经使用过某一个数字,来搜索剩余两个数字,如果后面这个数字再次出现,那么就不必要再搜索一次了,搜索的结果就是重复的结果,是无意义的。

为了使计算方便,首先做个排序,然后依次判断,如果重复出现就不再计算,这样下来时间复杂度降到了O(n^3)

Runtime: 139 ms

Your runtime beats 1.36% of cpp submissions.

还是很可怜的成绩,需要继续优化。

#include <iostream>
#include <vector> using namespace std; vector<vector<int> > threeSum(vector<int>& nums); void sortv(vector<int> &vec); vector<vector<int> > threeSum(vector<int>& nums) {
vector< vector<int> >ret; if (nums.size() < 2) {
return ret;
} if (nums.size() == 3) {
if (nums[1] + nums[2] + nums[0] == 0) {
ret.push_back(nums);
} return ret;
} sortv(nums); int size = nums.size();
int last_1;
int last_2;
int last_3; for (vector<int>::const_iterator it = nums.cbegin(); it != (nums.cend() - 2); it++) {
int first = *it;
// cout<<"first and last_1"<<first<<last_1<<endl;
if (it != nums.cbegin()) {
if (first == last_1) {
// cout<<"same first"<<first<<endl;
continue;
}
} last_1 = first;
// 2rd Loop
for (vector<int>::const_iterator it2 = it + 1; it2 != (nums.end() - 1); it2++) {
int second = *it2;
// cout<<"No.2 for loop: "<<(*it2)<<" last2: "<<last_2<<endl;
if (it2 != it + 1) {
if (second == last_2) {
// cout<<"same second"<<second<<endl;
continue;
}
}
last_2 = second;
// Third loop
for (vector<int>::const_iterator it3 = it2 + 1; it3 != nums.end(); it3++) {
int third = *it3;
if (it3 != it2 + 1) {
if (third == last_3) {
// cout<<"same third"<<third<<endl;
continue;
}
}
last_3 = third; if (*it3 + second + first) {
continue;
} else {
vector<int> tmp;
tmp.push_back(first);
tmp.push_back(second);
tmp.push_back(*it3);
ret.push_back(tmp);
// cout<< *it3 << second << first <<endl;
}
} }
} return ret;
} void sortv(vector<int> &vec) {
for (int i = vec.size(); i > 0; --i) {
for (int j = 0; j < i - 1; ++j) {
if (vec[j] > vec[j + 1]) {
int t = vec[j];
vec[j] = vec[j + 1];
vec[j + 1] = t;
}
}
} // for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
// cout<<"Sort:"<<(*it)<<endl;
// }
}

果然自己脑子还是不够用,上网查了一下人家的解法,复杂度直接降到O(n^2).具体代码可见: 九章 - 3Sum 人家如何减少一个量级的复杂度呢?将数组排序以后,首先一个完整的循环,nums[i],那么我们需要的另两个数的和就应该是 -nums[i]. 现在有两个游标,一个从头,一个从尾。因为无论如何不可能三个数值都为正或者都负,肯定是一个更靠近头部,一个更靠近尾部。如果求得的和比我们要的小,说明起点太小,往前面挪一个,反则往后挪。主要在搜寻中遇到重复的数据也一样把他去除掉。

class Solution {
public:
/**
* @param numbers : Give an array numbers of n integer
* @return : Find all unique triplets in the array which gives the sum of zero.
*/
vector<vector<int> > threeSum(vector<int> &nums) {
vector<vector<int> > result; sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// two sum;
int start = i + 1, end = nums.size() - 1;
int target = -nums[i];
while (start < end) {
if (start > i + 1 && nums[start - 1] == nums[start]) {
start++;
continue;
}
if (nums[start] + nums[end] < target) {
start++;
} else if (nums[start] + nums[end] > target) {
end--;
} else {
vector<int> triple;
triple.push_back(nums[i]);
triple.push_back(nums[start]);
triple.push_back(nums[end]);
result.push_back(triple);
start++;
}
}
} return result;
}
};

LeetCode: 3Sum的更多相关文章

  1. [LeetCode] 3Sum Smaller 三数之和较小值

    Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 < ...

  2. [LeetCode] 3Sum Closest 最近三数之和

    Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

  3. [LeetCode] 3Sum 三数之和

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  4. LeetCode 3Sum Smaller

    原题链接在这里:https://leetcode.com/problems/3sum-smaller/ 题目: Given an array of n integers nums and a targ ...

  5. leetcode — 3sum

    import java.util.*; /** * Source : https://oj.leetcode.com/problems/3sum/ * * Created by lverpeng on ...

  6. LeetCode:3Sum, 3Sum Closest, 4Sum

    3Sum Closest Given an array S of n integers, find three integers in S such that the sum is closest t ...

  7. Leetcode 3Sum Closest

    Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

  8. leetcode—3sum

    1.题目描述 Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find ...

  9. Leetcode 3Sum Closet

    二手和3Sum像几乎相同的想法.二进制搜索.关键修剪.但是,在修剪做出很多错误. 然后还有一个更加速了原来的想法O(n^2). #include<iostream> #include &l ...

随机推荐

  1. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  2. 微信小程序体验(2):驴妈妈景区门票即买即游

    驴妈妈因为出色的运营能力,被腾讯选为首批小程序内测单位.驴妈妈的技术开发团队在很短的时间内完成了开发任务,并积极参与到张小龙团队的内测问题反馈.驴妈妈认为,移动互联网时代,微信是巨大的流量入口,也是旅 ...

  3. 探索ASP.NET MVC5系列之~~~5.缓存篇(页面缓存+二级缓存)

    其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...

  4. JavaScript var关键字、变量的状态、异常处理、命名规范等介绍

    本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...

  5. Minor【 PHP框架】1.简介

    1.1 Minor是什么 Minor是一个简单但是优秀的符合PSR4的PHP框架,It just did what a framework should do. 只做一个框架应该做的,简单而又强大! ...

  6. 学习ASP.NET Core, 怎能不了解请求处理管道[6]: 管道是如何随着WebHost的开启被构建出来的?

    注册的服务器和中间件共同构成了ASP.NET Core用于处理请求的管道, 这样一个管道是在我们启动作为应用宿主的WebHost时构建出来的.要深刻了解这个管道是如何被构建出来的,我们就必须对WebH ...

  7. C#中将DataTable导出为HTML的方法

    今天我要向大家分享一种将DataTable导出为到HTML格式的方法.有时我们需要HTML格式的输出数据, 以下代码就可以帮助我们达到目的,. 首先,我们要绑定DataTable和 DataGridV ...

  8. 创建APPID&&部署服务端教程

    创建APPID&&部署服务端 一.创建APPID 1.打开https://console.developers.google.com ,左击顶部Project,然后左击创建项目 2.输 ...

  9. Android之SAX解析XML

    一.SAX解析方法介绍 SAX(Simple API for XML)是一个解析速度快并且占用内存少的XML解析器,非常适合用于Android等移动设备. SAX解析器是一种基于事件的解析器,事件驱动 ...

  10. 洛谷P1547 Out of Hay

    题目背景 奶牛爱干草 题目描述 Bessie 计划调查N (2 <= N <= 2,000)个农场的干草情况,它从1号农场出发.农场之间总共有M (1 <= M <= 10,0 ...