Q:
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] ]A:
这道题昨天我就着手看了,但是我没有很好的思路,能想到的办法也就是分治类似于得到一个数字nums[0],然后找出她的相反数这样。然后我去查了查资料,有一个解决ksum的专题,好像说这种问题很难有好的解法,应该最好就是O(n^(k-1))的复杂度。所以按照昨天的想法这样做。
1、解决这类问题为了速度肯定是要先排序的。
2、取第x个数字x从0到n-1
3、对比剩下的nums[i+1]nums[n-1](x=i);
4、如果nums[i+1]+nums[n-1]>target,那么只能n--才可能==target
如果nums[i+1]+nums[n-1]<target,那么只能i++才可能==target
5、如果i==n或者 nums[i+1]+nums[n-1]==target推出循环,x++;
这样的话一般排序最差O(n^2)而后面的排序最差也是O(n^2)所以能够保证整体算法O(n^2)。
下面我们上代码看看:
public static void main(String[] args){
//System.out.println();
int[] nums = {-5,1,-3,-1,-4,-2,4,-1,-1};
// nums = paixu(nums,0,nums.length-1);
// for(int i : nums){
// System.out.println(i);
// }
System.out.println(method(nums));
}
public static List<List<Integer>> method(int[] nums){
List<List<Integer>> list= new ArrayList<List<Integer>>() ;
if(nums.length<3)
return list;
nums = paixu(nums,0,nums.length-1);
for(int i : nums){
System.out.println(i);
}
//找3sum
for(int i = 0;i<nums.length;i++){
if(i==nums.length-1)
return list;
for(int j = i+1,k=(nums.length-1);j!=k;){
if(nums[j]+nums[k]>(-nums[i])){
k--;
}
else if(nums[j]+nums[k]<(-nums[i])){
j++;
}else if(nums[j]+nums[k]==(-nums[i])){
List numList = new ArrayList<Integer>();
numList.add(nums[i]);
numList.add(nums[j]);
numList.add(nums[k]);
//去重
boolean flag = true;
for(List l:list){
if(l.toString().equals(numList.toString())){
flag = false;
break;
}
}
if(flag)
list.add(numList);
k--;
}
}
}
return list;
}
public static int[] paixu(int[] nums,int start,int end){
//排序
int key = nums[start];
int i = start,j=end;
while(i<j){
while(i<j&&nums[j]>=key){
j--;
}
nums[i] = nums[j];
while(i<j&&nums[i]<=key){
i++;
}
nums[j] = nums[i];
}
nums[j] = key;
//System.out.println("start:"+start+" end"+end);
if(start!=end){
//System.out.println("j"+j);
if(j==start)
paixu(nums, start+1, end);
else if(j==end)
paixu(nums, start, end-1);
else{
paixu(nums,start,j-1);
paixu(nums,j+1,end);
}
}
return nums;
}
虽然想法不难,但是边界检测真的很头疼啊。
后来发现有一个长串leetcode的监测例子通不过,时间太久,然后代码改成了这样:
public static void main(String[] args){
//System.out.println();
int[] nums = {0,0,0};
// nums = paixu(nums,0,nums.length-1);
// for(int i : nums){
// System.out.println(i);
// }
System.out.println(method(nums));
}
public static List<List<Integer>> method(int[] nums){
List<List<Integer>> list= new ArrayList<List<Integer>>() ;
if(nums.length<3)
return list;
//nums = paixu(nums,0,nums.length-1);
Arrays.sort(nums);
for(int i : nums){
System.out.println(i);
}
//找3sum
for(int i = 0;i<nums.length-2;i++){
for(int j = i+1,k=(nums.length-1);j<k;){
if(nums[j]+nums[k]>(-nums[i])){
k--;
}
else if(nums[j]+nums[k]<(-nums[i])){
j++;
}else{// if(nums[j]+nums[k]==(-nums[i]))
List numList = new ArrayList<Integer>();
numList.add(nums[i]);
numList.add(nums[j]);
numList.add(nums[k]);
System.out.println("j:"+j);
while (j <k && nums[i] == nums[i+1]&&i<nums.length-2) i++;
while (j < k && nums[k] == nums[k-1]) k--;
list.add(numList);
j++;
}
}
}
return list;
}
public static int[] paixu(int[] nums,int start,int end){
//排序
int key = nums[start];
int i = start,j=end;
while(i<j){
while(i<j&&nums[j]>=key){
j--;
}
nums[i] = nums[j];
while(i<j&&nums[i]<=key){
i++;
}
nums[j] = nums[i];
}
nums[j] = key;
//System.out.println("start:"+start+" end"+end);
if(start!=end){
//System.out.println("j"+j);
if(j==start)
paixu(nums, start+1, end);
else if(j==end)
paixu(nums, start, end-1);
else{
paixu(nums,start,j-1);
paixu(nums,j+1,end);
}
}
return nums;
}
结果还是不行。。。最后去掉了method函数中的输出可以了