15. 3Sum
- Total Accepted: 127471
- Total Submissions: 659843
- Difficulty: Medium
Given an array S of n integers, are there elements a,b,c inS such thata +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] ]
我的代码:(暴力)
目前问题:没有解决重复问题。
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
if(nums == null) return null;
ArrayList<Integer> res ;
List<List<Integer>> result = new ArrayList<List<Integer>>();
for(int i = 0 ; i < nums.length ; i++)
for(int j = 0 ; j < nums.length ; j++)
for(int k = 0 ; k < nums.length ; k++ )
if(nums[i]+nums[j]+nums[k] == 0 && i != j && j != k && i != k ){
res = new ArrayList<Integer>();
res.add(nums[i]);
res.add(nums[j]);
res.add(nums[k]);
result.add(res);
}
return result;
}
}
分析:时间复杂度为O(n3)。
代码(二)(目前运行时长25ms)
代码思路:http://www.cnblogs.com/ganganloveu/p/3832180.html
先升序排序,然后用第一重for循环确定第一个数字。
然后在第二重循环里,第二、第三个数字分别从两端往中间扫。
如果三个数的sum等于0,得到一组解。
如果三个数的sum小于0,说明需要增大,所以第二个数往右移。
如果三个数的sum大于0,说明需要减小,所以第三个数往左移。
时间复杂度:O(n2)
注意:
1、排序之后天然满足non-descending order的要求
2、为了避免重复,在没有空间要求情况下可以用map,但是也可以跳过重复元素来做import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<Integer> tmp_nums = new ArrayList<Integer>();
ArrayList<Integer> res ;
List<List<Integer>> result = new ArrayList<List<Integer>>();
if(nums.length < 3) return result;
for(int i = 0 ; i < nums.length ; i ++){
tmp_nums.add(nums[i]);
}
Collections.sort(tmp_nums);
for (int i = 0; i < tmp_nums.size(); ++i) {
while (i > 0 && i < tmp_nums.size() && tmp_nums.get(i) == tmp_nums.get(i-1) ){
i++;
}
int j = i + 1;
int k = tmp_nums.size() - 1;
while (j < k ) {
if (tmp_nums.get(i) + tmp_nums.get(j) + tmp_nums.get(k) == 0) {
res = new ArrayList<Integer>();
res.add(tmp_nums.get(i));
res.add(tmp_nums.get(j));
res.add(tmp_nums.get(k));
result.add(res);
j++;
k--;
while (j < k && tmp_nums.get(j) == tmp_nums.get(j - 1))
j++;
while (k > j && tmp_nums.get(k) == tmp_nums.get(k + 1))
k--;
} else if (tmp_nums.get(i) + tmp_nums.get(j) + tmp_nums.get(k) < 0) {
j++;
while (j < k && tmp_nums.get(j) == tmp_nums.get(j - 1))
j++;
} else if (tmp_nums.get(i) + tmp_nums.get(j) + tmp_nums.get(k) > 0) {
k--;
while (k > j && tmp_nums.get(k) == tmp_nums.get(k + 1))
k--;
}
}
}
return result;
}
}
分析:跳过重复元素很重要,注意边界值判断。要记得一开始判断空。时间复杂度O(n)。但是目前此方法运行很慢。
311 / 311 test cases passed.
Status: Accepted | |
Runtime:
26 ms
|
Submitted:
0 minutes ago
|
代码3:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int> > vvi;
if (num.size() < 3) return vvi;
std::sort(num.begin(), num.end(), [] (int a, int b) {return a < b;});
int f, s, t;
for (f = 0; f < num.size()-2; ++f) {
if (f > 0 && num[f] == num[f-1])
continue;
for (s = f + 1; s < num.size() - 1; ++s) {
if (s != f+1 && num[s] == num[s-1])
continue;
t = s + 1;
while (num[f]+num[s]+num[t] <= 0) {
if (num[f]+num[s]+num[t] == 0) {
vector<int> vi;
vi.push_back(num[f]);
vi.push_back(num[s]);
vi.push_back(num[t]);
vvi.push_back(vi);
break;
} else if (t < num.size() - 1) {
t++;
} else {
break;
}
}
}
}
return vvi;
}
分析:代码易懂。但是时间复杂度O(n3)。相当于是解决了重复问题的暴力。