版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vivianXuejun/article/details/79295699
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]
]
一开始拿到这道题目的时候,首先想到的是先排序再查找,排序的时候我首选的是冒泡排序,但是效率较低,虽然最后代码通过了,但是远比java自带的排序方法要耗时。其次,在查找的时候,我有点无从下手,想了很久后来借鉴了网上的做法,做到固定一个数之后使用双指针查找的方法,这个方法是比较好,但是需要考虑一点就是要去重,这是题目要求的。
先贴代码一:
//Runtime: 109 ms
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists = new ArrayList<List<Integer>>();
if(nums.length < 3)return lists;
//排序
//Arrays.sort(nums);
int temp = 0;
boolean flag = false;
for(int k=nums.length - 1; k>0; k--){
for(int f=0; f<k; f++){
if(nums[f]>nums[f+1]){
temp = nums[f];
nums[f] = nums[f+1];
nums[f+1] = temp;
flag = true;
}
}
if(false == flag){
break;
}
}
//查找(固定一个数,采用双指针查找)
for(int i=0; i<nums.length; i++){
//固定一个数
int s1 = i;
//双指针
int left = i+1; int right = nums.length-1;
//如果nums[i]==nums[i-1]说明前后两者相同,那么计算出来的结果也会相同
if(i>0 && nums[i]==nums[i-1]){
continue;
}
while(left<right){
if(nums[s1] + nums[left] + nums[right] == 0){
List<Integer> list = new ArrayList<Integer>();
list.add(nums[s1]);
list.add(nums[left]);
list.add(nums[right]);
lists.add(list);
left++;
right--;
//如果left与right在移动中前后相同,需要跳过,因为与之前的结果是一样的,会重复
while(left < right && nums[left] == nums[left-1]) left++;
while(left < right && nums[right] == nums[right+1]) right--;
}else if(nums[s1] + nums[left] + nums[right] > 0){
right--;
}else{
left++;
}
}
}
return lists;
}
}
代码一使用的是冒泡排序,代码二:
//Runtime: 76 ms
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists = new ArrayList<List<Integer>>();
if(nums.length < 3)return lists;
//排序
Arrays.sort(nums);
//查找(固定一个数,采用双指针查找)
for(int i=0; i<nums.length; i++){
//固定一个数
int s1 = i;
//双指针
int left = i+1; int right = nums.length-1;
//如果nums[i]==nums[i-1]说明前后两者相同,那么计算出来的结果也会相同
if(i>0 && nums[i]==nums[i-1]){
continue;
}
while(left<right){
if(nums[s1] + nums[left] + nums[right] == 0){
List<Integer> list = new ArrayList<Integer>();
list.add(nums[s1]);
list.add(nums[left]);
list.add(nums[right]);
lists.add(list);
left++;
right--;
//如果left与right在移动中前后相同,需要跳过,因为与之前的结果是一样的,会重复
while(left < right && nums[left] == nums[left-1]) left++;
while(left < right && nums[right] == nums[right+1]) right--;
}else if(nums[s1] + nums[left] + nums[right] > 0){
right--;
}else{
left++;
}
}
}
return lists;
}
}
其实这道题需要注意的是在遍历循环查找的过程中去除重复数字,有几个条件都是缺一不可的,包括在对固定数字的去重、对左右指针的移动的去重,只要解决了这些问题,这道题与2Sum的题目基本思路一样,也就迎刃而解了。(我在这块吃过亏,就是因为忽略左右指针的去重导致修改多次)
介绍一篇优秀博文,里面的思路写的十分详细:
http://blog.csdn.net/zhouworld16/article/details/16917071